MVC DropDownList values ​​sent to model are unrelated

DropDownLists is probably my favorite part of working with an MVC map. I have several drop-down lists in my form whose selected values ​​I need to pass to ActionResult, which takes the model as its parameter.

The markup is as follows:

<div class="editor-label">
    @Html.LabelFor(model => model.FileType)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.FileType.Variety, (SelectList)ViewBag.FileTypes)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.Status)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.Status.Status, (SelectList)ViewBag.Status)
</div>

And my controller action looks like this:

[HttpPost]
public ActionResult Create(int reviewid, ReviewedFile file)
{
    if (ModelState.IsValid)
    {
        UpdateModel(file);
    }

    //repository.Add(file);

    return RedirectToAction("Files", "Reviews", new { reviewid = reviewid, id = file.ReviewedFileId });
}

This should be good and good, except that the values ​​from the drop-down lists are published as null. When I look further into ModelState errors, the cause is defined as:

The conversion of parameters from the type 'System.String' to the input of type 'PeerCodeReview.Models.OutcomeStatus' failed because the type converter cannot convert between these types.

, . , : ?

, , FormCollection, , .

+1
2

:

<div class="editor-label">
    @Html.LabelFor(model => model.FileType)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.FileType.Id, (SelectList)ViewBag.FileTypes)
</div>

<div class="editor-label">
    @Html.LabelFor(model => model.Status)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.Status.Id, (SelectList)ViewBag.Status)
</div>
+2

, .

, :

public class LookupModelBinder<TModel> : DefaultModelBinder
    where TModel : class
{
    private string _key;

    public LookupModelBinder(string key = null)
    {
        _key = key ?? typeof(TModel).Name;
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var dbSession = ((IControllerWithSession)controllerContext.Controller).DbSession;

        var modelName = bindingContext.ModelName;
        TModel model = null;
        ValueProviderResult vpResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (vpResult != null)
        {
            bindingContext.ModelState.SetModelValue(modelName, vpResult);
            var id = (int?)vpResult.ConvertTo(typeof(int));
            model = id == null ? null : dbSession.Get<TModel>(id.Value);
        }
        if (model == null)
        {
            ModelValidator requiredValidator = ModelValidatorProviders.Providers.GetValidators(bindingContext.ModelMetadata, controllerContext).Where(v => v.IsRequired).FirstOrDefault();
            if (requiredValidator != null)
            {
                foreach (ModelValidationResult validationResult in requiredValidator.Validate(bindingContext.Model))
                {
                    bindingContext.ModelState.AddModelError(modelName, validationResult.Message);
                }
            }
        }
        return model;
    }
}

TModel - , . , , . , , .

Global.asax.

binders[typeof(EmploymentType)] = new LookupModelBinder<EmploymentType>();

, . , .

binders[typeof(EmploymentType)] = new LookupModelBinder<EmploymentType>("ControlName");
+3

All Articles