Search code examples
c#asp.net-mvcasp.net-core-2.2

Creating a form and binding to a class without a datatabase


I'm new to learning MVC and could really use some help- as I'm trying to move on from ASP.NET Web Forms. I have a custom web API for all my database transactions that is very efficient and reliable. I've recoded it in .NET Core.

My problem is that I'm finding most of the model binding examples pertaining to MVC are composed of Entity Framework examples. I'm looking for help showing how to link a ViewModel to a Controller with get() post(form) actions. I need to see how to bind to a radio button list, etc...

I'm working with the class below, which has removed the database connections to simplify the answers/suggestions.

public class BuildSearch
{
    //Bootstrap date entry
    public DateTime StartDate { get; set; }
    //Bootstrap date entry
    public DateTime EndDate { get; set; }
    //Need this bound to a radio button list
    public List<GeoArea> GeoAreas { get; set; }

    public BuildSearch()
        {
            GeoAreas = new List<GeoArea>();
           // StartDate = DateTime.Parse(DateTime.Now.AddDays(-31).ToShortDateString());
           //  EndDate = DateTime.Parse(DateTime.Now.ToShortDateString());

            GeoAreas.Add(new GeoArea { GeoAreaItem = "Region", Id = 0 });
            GeoAreas.Add(new GeoArea { GeoAreaItem = "Manager1", Id = 1 });
            GeoAreas.Add(new GeoArea { GeoAreaItem = "Manager2", Id = 2 });
     } 
 }

public class GeoArea
{
     public int Id { get; set; }
     public string GeoAreaItem { get; set; }
}

I'm trying to create a view, that will display this data, and then allow for me to post back the user edits. I'm purposely looking to keep the example simple as once I figure out how to post back, with the updated data I can handle the pass off to a web API to do the work I need to be done. Just frustrated trying to figure out how I bind to this type of class.


Solution

  • For the radio buttons I would add a property to your BuildSearch class called GeoAreaId. The radio button selection will be model bound to this property on post back. Your BuildSearch class therefore becomes

    public class BuildSearch
    {
        //Bootstrap date entry
        public DateTime StartDate { get; set; }
        //Bootstrap date entry
        public DateTime EndDate { get; set; }
    
        public int GeoAreaId { get; set; } //added field
    
    
        //Need this bound to a radio button list
        public List<GeoArea> GeoAreas { get; set; }
        public BuildSearch()
        {
            GeoAreas = new List<GeoArea>();
            //   StartDate = DateTime.Parse(DateTime.Now.AddDays(-31).ToShortDateString());
            //  EndDate = DateTime.Parse(DateTime.Now.ToShortDateString());
    
            GeoAreas.Add(new GeoArea { GeoAreaItem = "Region", Id = 0 });
            GeoAreas.Add(new GeoArea { GeoAreaItem = "Manager1", Id = 1 });
            GeoAreas.Add(new GeoArea { GeoAreaItem = "Manager2", Id = 2 });
        }
        public class GeoArea
        {
            public int Id { get; set; }
            public string GeoAreaItem { get; set; }
        }
    }
    

    Your get method in your controller will look something like this

        public IActionResult Search()
        {
            var buildSearch = new BuildSearch();
            return View(buildSearch);
        }
    

    Your view will need to look something like this

    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @model  BuildSearch
    
    <form asp-controller="Home" asp-action="Search" method="post">   
    
        <label asp-for="StartDate">Start date</label>
        <input asp-for="StartDate" />
        <label asp-for="EndDate">End date</label>
        <input asp-for="EndDate" />
    
        <fieldset>
            <legend>
                GeoArea
            </legend>
            @foreach (var item in Model.GeoAreas)
            {
                <input type="radio" name="GeoAreaId" value="@item.Id" />
                @item.GeoAreaItem
            }
        </fieldset>
    
        <input type="submit" />
    </form>
    

    For the radio buttons note how the name attribute matches the new property GeoAreaId that I added to your BuildSearch class. This is important for the model binding to work.

    Then your post method in your controller will need to look like this

        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Search(BuildSearch buildSearch)
        {
            //...
        }
    

    To see what happens set a break point inside this method. Run the code, enter some values into the form and click submit. When the code has stopped inside hover over buildSearch and you will see the model binding has worked. The properties StartDate, EndDate and GeoAreaId will contain the values that you need from the form.