2

A few days ago I asked this question about jquery ajax function invoking action in ASP.NET MVC controller. It's now working the way it's supposed to but I encountered another problem and I've been trying to solve it since then.

Scenario is that the player is creating a new character and is given free points to modify the character stats (strenght, agility and intelligence). I'm using view model to pass data from controller to view and TempData["model"] for passing model between controller actions. Everything looks ok on server side. On click, ajax POST request is sent to server invoking ChangeStat method, character stats are modified in the model. Then I redirect to action which renders the View.

My problem is that the data displayed in the View are still the same (i.e. not updated according to modified model). I've read that it's due to MVC validation and so HTML helpers first chceck for old value to display when rendering the same view. I suppose that it's quite a common problem but I wasn't able to find a solution. I've tried using ViewData instead of model, partial view with model/with ViewData but with no result. Below are code snippets. Hope we can find a solution or maybe my approach is wrong and there is better practice to solve this.

Controller action for changing stats:

[HttpPost]
public ActionResult ChangeStat(LobbyModels.StatChange stat) 
{
    int changeCoef = 0;
    LobbyModels.CreateCharModel model = (LobbyModels.CreateCharModel)TempData["model"];

    if (model.CharFreePts == 0)
    {
        return RedirectToAction("Create");
    }

    switch (stat.ActionName)
    { 
        case "Inc":
            changeCoef = 1;
            break;
        case "Dec":
            changeCoef = -1;
            break;
    }

    switch (stat.StatName)
    { 
        case "Str":
            model.CharStr = model.CharStr + changeCoef;
            break;
        case "Agi":
            model.CharAgi = model.CharAgi + changeCoef;
            break;
        case "Int":
            model.CharInt = model.CharInt + changeCoef;
            break;
    }

    model.CharFreePts = model.CharFreePts + (changeCoef * (-1));
    TempData["model"] = model;

    return RedirectToAction("Create");
}

Create method which renders the view:

public ActionResult Create()
{
    LobbyModels.CreateCharModel model = LobbyModels.CreateCharModel)TempData["model"];
    if (model == null)
    {
        // null model handling
    }

    TempData["model"] = model;
    return View(model);
}

and in View I render data from model with html helpers

<div id="CharStats">
    <%= Html.TextBoxFor(m => m.CharStr)%>
    <input type="button" id="Str_Inc" value="+" />
    <input type="button" id="Str_Dec" value="-" />
    <%= Html.TextBoxFor(m => m.CharAgi)%>
    <input type="button" id="Agi_Inc" value="+" />
    <input type="button" id="Agi_Dec" value="-" />
    <%= Html.TextBoxFor(m => m.CharInt)%>
    <input type="button" id="Int_Inc" value="+" />
    <input type="button" id="Int_Dec" value="-" />
    <br />
    <%= Html.TextBoxFor(m => m.CharFreePts)%>
</div>

ChangeStat function is missing some logic but that's not a problem for now. My point is that I need to update textbox value according to current model data (or maybe try different approach completely).

Community
  • 1
  • 1
  • why not having an action returning a JsonResult and then use some client side jQuery to set the UI ? Code can be shared by defining a [NonAction] method in the controller. – BigMike Apr 02 '12 at 09:23

1 Answers1

1

I am agreeing with @BigMike, you should be handing a JsonResult back to the View. Also, for best practice you should validate entries before the call to the action, that way you aren't sending an ajax request if you don't have to. So if you are validating before the ajax POST, then you can render the UI change before the ajax POST and use a void action for updating the data on the server.

bdparrish
  • 3,216
  • 3
  • 37
  • 58