12

我有以下代码:

[HttpGet]
public ActionResult Edit(int req)
{
    var viewModel = new  EditViewModel();
    viewModel.RequestId = int;
    return View(viewModel);
}

[HttpPost]
Public ActionResult Edit(EditViewModel viewModel)
{
// some code here...
}

它工作正常:发布编辑表单时,我有被调用的动作控制器。

现在我修改了一些我的代码,如下所示:

[HttpGet]
public ActionResult Edit(int req)
{
    var viewModel = new  EditViewModel(req);
    return View(viewModel);
}

[HttpPost]
Public ActionResult Edit(EditViewModel viewModel)
{
// some code here...
}

public class EditViewModel()
{
    public EditViewModel(int req)
    {
        requestId = req; 
    }
    ...
}

在这个新版本中,我有一个带有构造函数的视图模型。

这一次,当我的表单被回发时,动作控制器永远不会被触发。

任何的想法?

谢谢。

4

2 回答 2

23

这很正常。默认模型绑定器无法再实例化您的视图模型,因为它没有无参数构造函数。如果要使用没有默认构造函数的视图模型,则必须编写自定义模型绑定器。

通常你不需要这样的自定义构造函数。您可以像这样简单地拥有您的视图模型:

public class EditViewModel()
{
    public int RequestId { get; set; }
}

和这样的 POST 动作:

[HttpPost]
public ActionResult Edit(EditViewModel viewModel)
{
    // some code here...
}

现在您所要做的就是发布requestId参数而不是req默认模型绑定器将完成这项工作。

如果由于某种原因您想使用带有自定义构造函数的视图模型,下面是自定义模型绑定器的示例:

public class EditViewModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var req = bindingContext.ValueProvider.GetValue("req");
        if (req == null)
        {
            throw new Exception("missing req parameter");
        }
        int reqValue;
        if (!int.TryParse(req.AttemptedValue, out reqValue))
        {
            throw new Exception(string.Format("The req parameter contains an invalid value: {0}", req.AttemptedValue));
        }

        return new EditViewModel(reqValue);
    }
}

这将在您的Application_Start

ModelBinders.Binders.Add(typeof(EditViewModel), new EditViewModelBinder());
于 2012-02-23T12:46:35.100 回答
4

Asp.Net Core 版本

public class EditViewModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var req = bindingContext.ValueProvider.GetValue("req");
        if (req == ValueProviderResult.None || string.IsNullOrEmpty(req.FirstValue))
        {
            bindingContext.ModelState.TryAddModelError("req", "Missing req parameter");
        }

        int reqValue;
        if (!int.TryParse(req.AttemptedValue, out reqValue))
        {
            bindingContext.ModelState.TryAddModelError($"The req parameter contains an invalid value: {req.AttemptedValue}");
        }

        var model = new EditViewModel(req.FirstValue);

        bindingContext.Result = ModelBindingResult.Success(model);
        return Task.CompletedTask;
    }
}

您不再需要向 startup.cs 注册任何内容。只需将活页夹分配给您的 ViewModel,您就可以离开了。

[ModelBinder(BinderType = typeof(EditViewModelBinder))]
public class EditViewModel
于 2018-06-04T10:10:52.513 回答