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
857 views
in Technique[技术] by (71.8m points)

asp.net mvc - MVC 3 Value Lost After Sent to Client

I must be missing something about how this works, because I can't figure this out. Maybe someone here can help.

My Address object has a property called ValidationStatus. It is not visible on the screen, but has a hidden field:

@Html.HiddenFor(model => model.ValidationStatus)

So, I run the program, open an existing address, which has a ValidationStatus of "OK", and change the address so that it is invalid. I then posts the form to the Controller. The object's Validate method calls the 3rd-party service, which returns an error. The code sets ValidationStatus to "Invalid" and return the View with a validation message.

When the View loads, ValidationStatus is properly set to "Invalid" as I can see by debugging the following statement in the View:

@if (Model.ValidationStatus == "Invalid") //show an additional field.

So I enters data in the new field and again post the form to the Controller. In the first line in the controller, I put a breakpoint and check collection["ValidationStatus"] in the immediate window. It is "OK" instead of "Invalid".

What am I missing here? Why didn't the value stick? There is nothing on the client side that can change that value.

Here's the controller code (pretty basic, really):

[HttpPost]
public ActionResult Index(FormCollection collection, string destinationControllerName)
{
    PrepareSecondaryData(); // loads drop-down lists in case the View needs to be returned

    try
    {
        if (!TryUpdateModel(_policy))
            return View(_policy);

        if (!_services.PolicyEditor.SavePolicy(_policy))
            return View(_policy);
    }
    catch (Exception exp)
    {
        UIHelper.Log(UIHelper.LogLevel.Error, this, "Error during Save", exp);
        ViewBag.Error = UIHelper.GenericErrorMessage();
        return View(_policy);
    }

    return RedirectToAction("Index", destinationControllerName);
}
See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

When rendering view to client, ModelState has the highest priority in providing values of model. That is the case in your situation. When the view is first time sent to client, ValidationStatus corresponding ModelState["ValidationStatus"] has not got value, so it takes model's value - "OK". When it is posted to server, ModelState["ValidationStatus"] is populated with "OK" - sent from hidden field from client. And when validated by 3rd party and returned back again, even though model.ValidationStatus == "Invalid", the ModelState["ValidationStatus"] == "OK", so according to higher priority of latter, ModelState sets value "OK" for the model. And the client gets value "OK" in the hidden field. To fix it, do something like

  ModelState["ValidationStatus"].Value = new ValueProviderResult("Invalid", "Invalid", CultureInfo.CurrentCulture);

General idea is that corresponding record in ModelState array should have correct value for the model.

UPDATE:

Or alternatively, clear value from modelstate, to make MVC use value from model. ModelState.Remove("ValidationStatus")


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

...