6

Im new to ASP.NET MVC and need some help.
When "P01" action is fired by post i receive the strongly typed model as parameter, change properties of this model instance and call "return View(model);".
In view im using "@Html.TextBoxFor(m => m.p01campo01)" syntax.
Someone here had a similar problem and get advice to use the syntax im using.
Someone here is using "<%=Html.TextBox("Person.LastName", ViewData.Model.LastName)%>" syntax.
The problem is when the view is rendered the textbox have the last posted value, not the value i assigned in controller.

Thanks for everyone that have tried to help me here, i put as answer the first answer that work.

There is my code:

*************************************************
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace MyTest.Models
{
    //-------
    public class testePg01
    {        
        [DataType(DataType.Text)]
        [Display(Name = "p01campo01")]
        public string p01campo01 { get; set; }

        [DataType(DataType.Text)]
        [Display(Name = "p01campo02")]
        public string p01campo02 { get; set; }

    }
    //-------
}
*************************************************

*************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyTest.Models;

namespace MyTest.Controllers
{
    public class TesteController : Controller
    {
        //-------
        [AcceptVerbs(HttpVerbs.Get)]        
        public ActionResult P01()
        {
            return View();
        }
        //-------
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateAntiForgeryToken]
        public ActionResult P01(testePg01 model)
        {
            model.p01campo01 = model.p01campo01 + "#updatedHereButNotInView";
            model.p01campo02 = model.p01campo02 + "#updatedHereButNotInView";
            return View(model); // it dont return updated
        }
        //-------

    }
}
*************************************************

*************************************************
@model MyTest.Models.testePg01

@{
    ViewBag.Title = "P01";
}

<h2>P01</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@Html.ValidationSummary(true, "Erro na pagina.")

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    <div>    
        <fieldset>
            <legend>Test P01</legend>

            <div class="editor-label">
                @Html.LabelFor(m => m.p01campo01)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.p01campo01)
                @Html.ValidationMessageFor(m => m.p01campo01)
            </div>

            <div class="editor-label">
                @Html.LabelFor(m => m.p01campo02)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.p01campo02)
                @Html.ValidationMessageFor(m => m.p01campo02)
            </div>
            <p>
                <input type="submit" value="P01" />
            </p>
        </fieldset>
    </div>
}
*************************************************

4 Answers 4

8

Model changes made in a post are not rendered by default. Instead it uses what was passed in the model to the controller method. To fix this, try adding:

ModelState.Clear();

immediately before the RedirectToAction.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, moving ModelState.Clear(); to end now.
6

Because it's an HttpPost HTML helpers are looking first to the POSTed data and only after that to the model.

You've to remove the property from the state:

[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult P01(testePg01 model)
{
    ModelState.Remove("p01campo01");
    ModelState.Remove("p01campo02");

    model.p01campo01 = model.p01campo01 + "#updatedHereButNotInView";
    model.p01campo02 = model.p01campo02 + "#updatedHereButNotInView";

    return View(model);         
}

Because ModelState is a dictionary you can also use Clear() to remove the all properties from the state:

ModelState.Clear();

BTW, on MVC3 you can use [HttpPost] and [HttpGet] insted of [Acceptverb(...)]

2 Comments

Thanks a lot, your second answer works for me. I changed to [HttpPost] too. I dont understand the first answer, do you told me to remove "[AcceptVerbs(HttpVerbs.Post)]" ? I created one action for get and another for post.
You're doing it right. One action to Post and another to Get. I was just saying that you can replace [AcceptVerbs(HttpVerbs.Post)] by [HttpPost] and [Acceptverbs(HttpVerbs.Get)] by [HttpGet]. They're exactly the same think but it gets more readable that way. It's just a detail :)
0

this is a very ugly workaround you can try

 public class TesteController : Controller
    {
        //-------
        [AcceptVerbs(HttpVerbs.Get)]        
        public ActionResult P01(string val1,string val2)
        {
            var model = new testePg01();
            if(!(String.IsEmptyOrNull(val1)&&String.IsEmptyOrNull(val2)))
                  { 
                       model.p01campo01  = val1;
                       model.p01campo02 = val2;

                  }
            return View(model);
        }
        //-------
        [AcceptVerbs(HttpVerbs.Post)]
        [ValidateAntiForgeryToken]
        public ActionResult P01(testePg01 model)
        {
            model.p01campo01 = model.p01campo01 + "#updatedHereButNotInView";
            model.p01campo02 = model.p01campo02 + "#updatedHereButNotInView";
            return RedirectToAction("P01",{val1=model.p01campo01,val2=model.p01campo02})          
        }
   }

Comments

0

Ignore the PRG suggestion bellow. It's ugly. Instead use:

public ActionResult P01(TestePg01 model)
    {
        model.P01campo01 = model.P01campo01 + "#updatedHereButNotInView";
        model.P01campo02 = model.P01campo02 + "#updatedHereButNotInView";
        ModelState.Clear(); //this will re-populate the view

        return View(model);
    }

Use post-redirect-get pattern:

    public class TesteController : Controller
{
    //-------
    [AcceptVerbs(HttpVerbs.Get)]
    public ViewResult P01(TestePg01 o)
    {
        return base.View(o);
    }
    //-------
    [AcceptVerbs(HttpVerbs.Post)]
    [ValidateAntiForgeryToken]
    public ActionResult P01Post(TestePg01 model)
    {
        model.P01campo01 = model.P01campo01 + "#updatedHereButNotInView";
        model.P01campo02 = model.P01campo02 + "#updatedHereButNotInView";
        return RedirectToAction("P01", model);
    }
    //-------
}

in the view:

@using (Html.BeginForm("P01Post", "Teste")) {//...}

2 Comments

Im new to MVC and never had listen about PRG, i found a link about it here: stevefenton.co.uk/Content/Blog/Date/201104/Blog/… and here: stevefenton.co.uk/Content/Blog/Date/201007/Blog/…
I found here: blog.jorritsalverda.nl/2010/03/10/… too, PRG is necessary ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.