0

I'm facing a strange issue with MVC retaining an incorrect int value, despite it being clearly set properly in a controller action.

Part of my Client controller action deals with creating a new client if the client name has changed, and setting the original client to deleted (yes, soft deletes can be bad, I know). My repository method uses nHibernate to insert the client into the db and returns the identity value (Client.ClientId). I can see that my ViewModel has the correct (new) ClientId value, but upon post back to the view, the incorrect (old) ClientId is retained. I can see it in Chrome inspector in the hidden input.

Here is my controller code:

[CustomAuthorization]
// GET: /Clients/Client/id
public ActionResult Client(int? id)
{
    if (id != null)
    {
        var viewModel = new ClientDetailViewModel();
        var client = new EntityManager<Client>().GetById(id.Value);
        viewModel.ClientList = Repository.GetClientList(client).ToList();

        //do more stuff...

        return View(viewModel);
    }

    return RedirectToAction("Index");
}

[CustomAuthorization]
[HttpPost]
public ActionResult Client(ClientDetailViewModel _viewModel)
{
    if (ModelState.IsValid)
    {
        //Get persistent client from db
        var pClient = new EntityManager<Client>().GetById(_viewModel.Client.ClientId);

        //check if client name has changed
        if (_viewModel.Client.OrgName != pClient.OrgName)
        {   
            //sets the persistent client as deleted, inserts the viewmodel client 
            //and sets _viewModel.Client.ClientId to the identity value 
            _viewModel.Client = Repository.ChangeClientName(_viewModel.Client, pClient);
        }

        //do some more stuff...
     }

     //the value of _viewModel.Client.ClientId is now the correct (new) one in debug
     return View(_viewModel);
}

Here is the Client class and property in question.

public class Client {
    public Client() {}
    public virtual int ClientId { get; set; }
}

And my view looks like this:

@using (Html.BeginForm("Client", "Clients", FormMethod.Post, new { @class="check-leave", @id = "clientedit_form" }))
{
    @Html.HiddenFor(m => m.Client.ClientId)

    @Html.EditorFor(m => m.Client)

    //a lot more html helpers and js...
 }

I realized that it was a better idea to use RedirectToAction, since we are dealing with a new client, so I tried the code below. However, despite seeing the correct new ClientId when I debug, the Client Get action still receives the old incorrect ClientId.

if (_viewModel.Client.OrgName != pClient.OrgName)
{   
    _viewModel.Client = Repository.ChangeClientName(_viewModel.Client, pClient);

    return RedirectToAction("Client",_viewModel.Client.ClientId);       
}

The only thing I can think of is perhaps the POST parameters are holding on to the old value despite what I'm doing in the controller.

wooters
  • 829
  • 6
  • 24
  • This is the normal behavior in MVC. The helpers bind to ModelState values (not the model value). You need to clear `ModelState` if you want to reset model state values, but you should be following the PRG pattern. [refer this answer](http://stackoverflow.com/questions/26654862/textboxfor-displaying-initial-value-not-the-value-updated-from-code/26664111#26664111) for more detail. –  Mar 05 '15 at 00:23
  • And the redirect should be `return RedirectToAction("Client", new { id = _viewModel.Client.ClientId });` –  Mar 05 '15 at 01:26
  • Thanks Stephen. I think I have broken the PRG pattern. After a successful save of client data, the application should show the same page with something like "Client saved successfully." I am returning the same view in the Client post action in order to do that, but it looks like I should be re-directing back to Client get action. – wooters Mar 05 '15 at 01:52
  • That's generally the accepted method, but an option is to use `ModelState["Client.ClientId"].Errors.Clear();` before you set the new `ClientId` value, then the hidden input will bind to the new value –  Mar 05 '15 at 02:18

0 Answers0