Using Automatic model generation from a class inside of a C# class rather than a razor file

  1. #1

    Using Automatic model generation from a class inside of a C# class rather than a razor file

    I am writing a lot of my UI declarations inside of C# classes because I really don't like the large razor files and the broken formatting. I like the reusability of this C# based UI classes, too.

    I know in razor you can do Html.X().StoreFor<Foo>();

    How would you do this in a plain C# class instead of writing an explicit model like this:

        protected static ext.Model BuildModel()
            {
               
                return new ext.Model()
                {
                    ID = "model",
                    IDProperty = "SupplierID",
                    Fields =
                    {
                        new ext.ModelField("SupplierID",ModelFieldType.Int),
                        new ext.ModelField("CompanyName"),
                        new ext.ModelField("ContactName"),
                        new ext.ModelField("ContactTitle"),
                        new ext.ModelField("Address"),
                        new ext.ModelField("City"),
                        new ext.ModelField("Region"),
                        new ext.ModelField("PostalCode"),
                        new ext.ModelField("Country"),
                        new ext.ModelField("Phone"),
                        new ext.ModelField("Fax")
                    }
                };
            }
    My confusion is that Html.X().StoreFor<Foo> returns a Builder which is really for razor declarations. I would like it to return the actual model class kind of like this:

      protected static ext.Panel BuildTopPanel()
            {
                return new ext.Panel()
                {
    
                    ID = "panel",
                    Region = ext.Region.North,
                    Border = false,
                    Height = 120,
                    BodyPadding = 6,
    
                    Html = "<h1>CRUD Grid Example</h1>" +
                        "<p>Demonstrates how to get data from HttpHandler and save using HttpHandler.</p>"
                };
            }

    And I have the same question for FormPanelForModel<Foo>()...
    Last edited by tolgaerdogus; Feb 03, 2017 at 1:34 PM.
  2. #2
    Hello @tolgaerdogus, and welcome to Ext.NET forums!

    I believe this guide showing how these Razor helper methods can be extended will give you an idea of what the helpers do in C# to bind the model so you can do the same in your code instead of using the helpers:

    - Creating Razor helper methods for custom controls

    Hope this helps!
    Fabrício Murta
    Developer & Support Expert
  3. #3
    Hello again!

    Here's a quick example to keep the razor syntax to a minimum yet take advantage of the helper:

    View:
    @using ExtNetPlaygroundMVC_current.Controllers;
    @model issuesController.c61744_model
    
    @{
        Layout = null;
    }
    
    @functions
    {
        private string GeneratePanel()
        {
            var panel = Html.X().GridPanelFor(Model.People).ToComponent();
            
            panel.ID = "GridPanel1";
            panel.Title = "Name List cbR";
            panel.Width = 300;
            panel.Height = 200;
            
            return panel.ToScript();
        }
    }
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <script type="text/javascript">
            Ext.onReady(function(){
                @Html.Raw(GeneratePanel());
            });
        </script>
    
    </head>
    <body>
        <div>
            @Html.X().ResourceManager()
    
            @* The function code above will return the equivalent code to:
            @(Html.X().GridPanelFor(Model)
                .ID("GridPanel1")
                .Title("Name List")
                .Width(300)
                .Height(200)
            )*@
        </div>
    </body>
    </html>
    Model+Controller (merged for simplicity)
    public class c61744_model
    {
        public class Person
        {
            public string FirstName { get; set; }
    
            public string LastName { get; set; }
        }
    
        public List<Person> People { get; set; }
    }
    
    public ActionResult c61744_ForModelFromController()
    {
        return View(new c61744_model
        {
            People = new List<c61744_model.Person>
            {
                new c61744_model.Person() { FirstName = "Firstname1", LastName = "Lastname1" },
                new c61744_model.Person() { FirstName = "Firstname2", LastName = "Lastname2" },
                new c61744_model.Person() { FirstName = "Firstname3", LastName = "Lastname3" },
                new c61744_model.Person() { FirstName = "Firstname4", LastName = "Lastname4" }
            }
        });
    }
    Hope this helps!
    Fabrício Murta
    Developer & Support Expert
  4. #4
    That is great but the only issue is that the generated Panel is not in a reusable file such that it can consumed from other razor views.

    I was hoping that I could capture this kind of logic in pure c# "view" classes that can get put together and reused in many different razor views.

    My main goal was the code formatting and the ability to take advantage of composability...

    So, I can't write the same or effectively equivalent code in the @functions section inside of a plain old c# file?

    Thanks
  5. #5
    Hello @tolgaerdogus!

    Maybe partial views is what you need then? Probably you'd need the razor part in order to explore the GridPanelFor<T> functionality, but maybe you can get to an acceptable solution for reusability using this, with part coming from the razor view and part coming from the controller, maybe.

    The starting point would be this example and then its "neighbor" examples: Dynamic Partial Rendering - Add Tab
    Fabrício Murta
    Developer & Support Expert
  6. #6
    Hello again!

    In case partial views nor the razor helpers are options, here's the way to make the panel from the example above with 100% C# code. That should work for WebForms examples too.

    Notice above we return the component's ToString() to leave it clear how the component is built. One way or another, at some point that script is used client-side to be built on the page. Several components can be encapsulated on a single script, for example, by wrapping them in an Ext.Net.Container.

    Here's what you should change in the example above:

    - create a method to simulate database access
        private issuesController.c61744_model getData()
        {
            return new issuesController.c61744_model
            {
                People = new List<issuesController.c61744_model.Person>
                {
                    new issuesController.c61744_model.Person() { FirstName = "Firstname1", LastName = "Lastname1" },
                    new issuesController.c61744_model.Person() { FirstName = "Firstname2", LastName = "Lastname2" },
                    new issuesController.c61744_model.Person() { FirstName = "Firstname3", LastName = "Lastname3" },
                    new issuesController.c61744_model.Person() { FirstName = "Firstname4", LastName = "Lastname4" }
                }
            };
        }
    - Then make the panel off this data and data type. I just replaced GeneratePanel() with this:

    private string GeneratePanel()
    {
        var panel = new GridPanel();
        panel.ID = "GridPanel1";
        panel.Title = "Name List cbR";
        panel.Width = 300;
        panel.Height = 200;
    
        // Create the panel's store. Will be bound to the panel later
        var store = new Store();
    
        // Init the store by the object with data.
        store.InitByObject(getData().People);
    
        // Giving the panel the data store
        panel.Store.Add(store);
    
        // Now the grid panel should also have the columns corresponding to the model
        panel.InitByType(typeof(issuesController.c61744_model.Person));
            
        return panel.ToScript();
    }
    And there you go, without the builder helper.

    The grid panel also has an InitByType() method, but the minimal and necessary for it to have the columns is what was shown.

    The grid panel creation process can be easily "bundled" on a method that receives its basic settings and object with data and binds both the store data and column setup like shown above... or maybe an extension method to the GridPanel class to init the store when it is initialized by object as well.

    I hope this helps!

Similar Threads

  1. Replies: 3
    Last Post: Feb 20, 2014, 4:24 AM
  2. Replies: 0
    Last Post: Oct 14, 2013, 2:35 PM
  3. Class Library - Razor intellisense MVC 3
    By Nesse in forum 2.x Help
    Replies: 6
    Last Post: Aug 04, 2013, 10:40 AM
  4. [CLOSED] FileUploadField in class file
    By logicspeak in forum 1.x Legacy Premium Help
    Replies: 2
    Last Post: Sep 26, 2011, 2:40 PM

Posting Permissions