Search code examples
c#asp.netasp.net-mvcasp.net-core-mvc-2.0

Form fields from the ASP.NET View appear NULL in the Controller


The form fields do not return the value of the form even thought the asp-controller and asp-action is stated. The form does go to the right controller function and returns the right view, however, it does the form object is NULL.

@using ActionAugerMVC.Models
@model Tuple<IEnumerable<Cities>,Content,IEnumerable<Content>,Quote>
@addTagHelper "*,Microsoft.AspNetCore.Mvc.TagHelpers"

 <div class="sidebar__item">
    <p class="subheading">Instant Quote Request</p>
       <form class="register__form" role="form" asp-controller="Plumbing" asp-action="QuoteForm" method="post">
             <div class="text-danger" asp-validation-summary="All"></div>
             <div class="form-group">

               <label class="sr-only">Full Name </label>
               <input asp-for="@Model.Item4.FullName" type="text" class="form-control" placeholder="Full name">
               </div>
               <div class="form-group">
                 <label class="sr-only">Your phone</label>
                 <input asp-for="@Model.Item4.Phone" type="tel" class="form-control" placeholder="Your phone">
                 <span asp-validation-for="@Model.Item4.Phone" class="text-danger"></span>
               </div>
               <div class="form-group">
                 <label class="sr-only">E-mail</label>
                 <input asp-for="@Model.Item4.Email" type="email" class="form-control" placeholder="E-mail">
                 <span asp-validation-for="@Model.Item4.Email" class="text-danger"></span>
               </div>
               <div class="form-group">
                 <label class="sr-only">Your Message</label>
                 <input asp-for="@Model.Item4.Message" type="text" class="form-control" placeholder="Your Message">
               </div>
                <input type="submit" value="Get a Quote Now" class="btn btn-accent btn-block">
         </form>
   </div> <!-- .sidebar__item -->

And the Controller looks like this, with the Quote object being null. The hard coded, values appear correctly in the view, but the Quote object returned by the form is null.

    [HttpPost]
    public IActionResult QuoteForm(Quote quote)
    {
        if (ModelState.IsValid)
        {
           /* quote.FullName = "Umar Aftab";
            quote.Email = "[email protected]";
            quote.City = "Calgary";
            quote.Message = "Test Message";
            quote.Phone = "6474543769";
            */

        }
        return View(quote);
    }

Solution

  • The issue is your use of a Tuple as your view's model combined with asp-for. For example, with something like:

    <input asp-for="@Model.Item4.FullName" type="text" class="form-control" placeholder="Full name">
    

    The name of the input is going to end up as Item4.FullName. However, your action accepts only Quote, which means the modelbinder needs the input to be named just FullName in order to bind it properly. You either need to accept the same model the view uses (though I've never tried posting a Tuple so not sure if that will even work), or you can use a partial view to work around the issue.

    Essentially, you just would need to move all the fields related to just Quote to a partial view. Then, in this view, you can include them via:

    @Html.Partial("_QuoteFields", Model.Item4)
    

    That should be enough psych Razor out enough to just name the fields like FullName instead of Item4.FullName. If it's not, then you may need to reset the HtmlFieldPrefix, via:

    @Html.Partial("_QuoteFields, Model.Item4, new ViewDataDictionary(ViewData) { TemplateInfo = new TemplateInfo {  HtmlFieldPrefix = "" } })