Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
134 views
in Technique[技术] by (71.8m points)

c# - Posting data when my view model has a constructor does not work

I have the following code:

[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...
}

It works fine: when the edit form is posted, I have the action controller who is called.

Now I modify some little bit my code like this:

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

In this new version, I have a view model with a contructor.

This time, when my form is posted back, the action controller is never triggered.

Any idea?

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

That's normal. The default model binder can no longer instantiate your view model as it doesn't have a parameterless constructor. You will have to write a custom model binder if you want to use view models that don't have a default constructor.

Normally you don't need such custom constructor. You could simply have your view model like that:

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

and the POST action like that:

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

and now all you have to do is POST the requestId parameter instead of req and the default model binder will do the job.

And if for some reason you wanted to use a view model with custom constructor, here's an example of how the custom model binder might look like:

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

which will be registered in your Application_Start:

ModelBinders.Binders.Add(typeof(EditViewModel), new EditViewModelBinder());

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...