Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 3 Model property is not being set in partial view called by html.action

I have an issue with my app, ill try explain by example, I have a form, this form exist of several textboxes and dropdown lists. For reusability I merged 3 drop down lists into a partial view, this partial view i load with @Html.Action, this works ok, when i start the form i see everything appears as it should be, although I dont know why but those required drop down lists directly are shown with red start and said it is required fields.

But when i fill everything in, and i select the values from the drop down lists, and i click on OK, the values from drop down lists are NULL.

I think it will be more comprehendable with a code example:

Main model:

public class FormModel
{
    [Required]
    public string UserName { get; set; }

    [Required]
    [Display(Name = "Birthdate")]
    public DateTime? Birthdate { get; set; }
    //This is what i'm talking about, that is not being set, the location
    public Location Location { get; set; } 
}

Here is the location class, which is then passed to the partial view and normally i think should be set, it looks like this:

public class Location
{
    [Required]
    [Display(Name = "Country")]
    public string CountryId { get; set; }

    [Required]
    [Display(Name = "Region")]
    public string RegionId { get; set; }

    [Required]
    [Display(Name = "City")]
    public string CityId { get; set; }
  }

Now we have a partial view for the location:

@model TestWebsite.Models.Location
<tr>
    <td class="editor-label">
        @Html.LabelFor(m => m.CountryId)
    </td>
    <td class="editor-field">
        @Html.DropDownListFor(m => m.CountryId, Model.Countries, "---select--", null)
    </td>
    <td>
        @Html.ValidationMessageFor(m => m.CountryId)
    </td>
</tr>
<!-- Region -->
<tr>
    <td class="editor-label">
        @Html.LabelFor(m => m.RegionId)
    </td>
    <td class="editor-field">
        @Html.DropDownListFor(m => m.RegionId, Enumerable.Empty<SelectListItem>(), "---select--", null)
    </td>
    <td>
        @Html.ValidationMessageFor(m => m.RegionId)
    </td>
</tr>
<!-- City -->
<tr>
    <td class="editor-label">
        @Html.LabelFor(m => m.CityId)
    </td>
    <td class="editor-field">
        @Html.DropDownListFor(m => m.CityId, Enumerable.Empty<SelectListItem>(), "---select--", null)
    </td>
    <td>
        @Html.ValidationMessageFor(m => m.CityId)
    </td>
</tr>

Then we call this partial view in the forms like this:

@Html.Action("LocationGroup", "Account", Model.Location)

And finally in the controller:

    [ChildActionOnly]
    public ActionResult LocationGroup(Location model)
    {
        model.Countries = GetCountries();
        return PartialView("_LocationView", model);
    }

I know it is a lot of code, but i hope you could help me ...

like image 227
Alnedru Avatar asked May 25 '13 18:05

Alnedru


Video Answer


1 Answers

I think you should use Editor Templates:

@model TestWebsite.Models.FormModel
@using(Html.BeginForm())
{
    @Html.EditorFor(x => x.Location)
    <input type="submit" value="save"/>
}

and add the partial inside ~/Views/[ControllerName]/EditorTemplates/Location.cshtml or ~/Views/Shared/EditorTemplates/Location.cshtml

code of template:

@model TestWebsite.Models.Location
<tr>
    <td class="editor-label">
        @Html.LabelFor(m => m.CountryId)
    </td>
    <td class="editor-field">
        @Html.DropDownListFor(m => m.CountryId, Model.Countries, "---select--", null)
    </td>
    <td>
        @Html.ValidationMessageFor(m => m.CountryId)
    </td>
</tr>
<!-- Region -->
<tr>
    <td class="editor-label">
        @Html.LabelFor(m => m.RegionId)
    </td>
    <td class="editor-field">
        @Html.DropDownListFor(m => m.RegionId, Enumerable.Empty<SelectListItem>(), "---select--", null)
    </td>
    <td>
        @Html.ValidationMessageFor(m => m.RegionId)
    </td>
</tr>
<!-- City -->
<tr>
    <td class="editor-label">
        @Html.LabelFor(m => m.CityId)
    </td>
    <td class="editor-field">
        @Html.DropDownListFor(m => m.CityId, Enumerable.Empty<SelectListItem>(), "---select--", null)
    </td>
    <td>
        @Html.ValidationMessageFor(m => m.CityId)
    </td>
</tr>

But if you prefer to have partial in some location (not follow conventions) you could specify the location:

@Html.EditorFor(x => x.Location, "~/Views/SpecifyLocation/_Location.cshtml")
like image 87
Xordal Avatar answered Nov 16 '22 04:11

Xordal