web-dev-qa-db-fra.com

Modèles complexes et vues partielles - problème de liaison de modèle dans ASP.NET MVC 3

J'ai 2 modèles dans mon exemple d'application MVC 3, SimpleModel et ComplexModel, comme indiqué ci-dessous:

public class SimpleModel
{
    public string Status { get; set; }
}

public class ComplexModel
{
    public ComplexModel()
    {
        Simple = new SimpleModel();
    }

    public SimpleModel Simple{ get; set; }
}

J'ai défini des vues pour ces modèles:

_SimplePartial.cshtml:

@model SimpleModel

@Html.LabelFor(model => model.Status)
@Html.EditorFor(model => model.Status)

et Complex.cshtml:

@model ComplexModel

@using (Html.BeginForm()) {

    @Html.Partial("_SimplePartial", Model.Simple)
    <input type="submit" value="Save" />
}

Après avoir soumis le formulaire, avec une valeur aléatoire entrée dans le champ Status, la valeur n'est pas liée à mon modèle. Le champ Status est NULL lorsque je vérifie le modèle dans l'action de mon contrôleur:

[HttpPost]
public ActionResult Complex(ComplexModel model)
{
    // model.Simple.Status is NULL, why ?
}

Pourquoi n'est-il pas lié? Je ne veux pas hériter de modèles. Dois-je écrire mes classeurs de modèles personnalisés pour un cas aussi simple?

Cordialement.

44
jwaliszko

Au lieu de:

@Html.Partial("_SimplePartial", Model.Simple)

Je vous recommanderais d'utiliser des modèles d'éditeur:

@model ComplexModel
@using (Html.BeginForm()) 
{
    @Html.EditorFor(x => x.Simple)
    <input type="submit" value="Save" />
}

puis mettez le simple partiel à l'intérieur ~/Views/Shared/EditorTemplates/SimpleModel.cshtml ou à l'intérieur ~/Views/Home/EditorTemplates/SimpleModel.cshtmlHome est le nom de votre contrôleur:

@model SimpleModel
@Html.LabelFor(model => model.Status)
@Html.EditorFor(model => model.Status)

Bien sûr, si vous préférez avoir le partiel dans un endroit spécial et ne pas suivre les conventions (pourquoi le feriez-vous?), Vous pouvez spécifier l'emplacement:

@Html.EditorFor(x => x.Simple, "~/Views/SomeUnexpectedLocation/_SimplePartial.cshtml")

alors tout se mettra en place comme prévu.

61
Darin Dimitrov

Comme Daniel Hall le suggère dans son blog , passez un ViewDataDictionary avec un TemplateInfoHtmlFieldPrefix est défini sur le nom de la propriété SimpleModel:

 @Html.Partial("_SimplePartial", Model.Simple, new ViewDataDictionary(ViewData)
    {
        TemplateInfo = new System.Web.Mvc.TemplateInfo
        {
            HtmlFieldPrefix = "Simple"
        }
    })
26
toralux