Свойство MVC 3 Model не задано в частичном виде, вызванное html.action

У меня проблема с моим приложением, плохо попробуйте объяснить на примере, у меня есть форма, эта форма существует из нескольких текстовых полей и выпадающих списков. Для повторного использования я объединил 3 выпадающих списка в частичное представление, это частичное представление, которое я загружаю с помощью @Html.Action, это работает нормально, когда я запускаю форму, я вижу, что все выглядит так, как должно быть, хотя я не знаю, почему, но требуемые выпадающие списки напрямую отображаются красным цветом и говорят, что это обязательные поля.

Но когда я заполняю все, и я выбираю значения из выпадающих списков, и я нажимаю ОК, значения из выпадающих списков равны NULL.

Я думаю, что это будет более понятным с примером кода:

Основная модель:

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; } 
}

Вот класс местоположения, который затем передается в частичный вид, и обычно я думаю, что он должен быть установлен, он выглядит следующим образом:

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; }
  }

Теперь у нас есть частичный вид для местоположения:

@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>

Затем мы называем этот частичный вид в таких формах:

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

И, наконец, в контроллере:

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

Я знаю, что много кода, но я надеюсь, что вы могли бы мне помочь...

Ответ 1

Я думаю, вы должны использовать Шаблоны редактора:

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

и добавьте частичное внутри ~/Views/[ControllerName]/EditorTemplates/Location.cshtml или ~/Views/Shared/EditorTemplates/Location.cshtml

код шаблона:

@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>

Но если вы предпочитаете частичное в каком-либо месте (не следуйте соглашениям), вы можете указать местоположение:

@Html.EditorFor(x => x.Location, "~/Views/SpecifyLocation/_Location.cshtml")

Ответ 2

Я согласен с Xordal, EditorTemplates - путь. Невероятно полезный материал. Одна вещь я заметил отсутствие SelectList. Мне может быть что-то упущено, но попробовали ли вы следующее:

 <td class="editor-label">
    @Html.LabelFor(m => m.CountryId)
</td>
<td class="editor-field">
    @Html.DropDownListFor(m => m.CountryId, new SelectList(Model.Countries, "CountryId" , "CountryName", null))
</td>
<td>
    @Html.ValidationMessageFor(m => m.CountryId)
</td>

Ответ 3

Попробуйте Html.RenderPartial вместо Html.Action