views:

69

answers:

1

Hi,

I'm using MVC 2 and EF4. If have a view that displays my Application (class) properties. Not all the properties are displayed in the view. There are a couple of the properties that need to be set once the submit button is clicked.

I'm getting client validation to pass, but my server validation is still failing. I receive an Application object in my CreateApplication action, I update a property, and do a ModelState.IsValid check. It is still false. I did a loop through my errors list and it displays the error text that I set on my SubmitterEmployeeNumber property using a Required data annotation. I did set it and I did update my model, but validation is still failing. Here is my code:

[HttpPost]
public ActionResult CreateApplication(Application application)
{
   application.SubmitterEmployeeNumber = "123456";

   TryUpdateModel(application);

   if (ModelState.IsValid)
   {
   }
}

Here is how I display the view:

public ActionResult CreateApplication()
{
   var viewModel = new ApplicationViewModel(new Application(), db.AccountTypes);

   return View(viewModel);
}

How do I get the validation to pass after I set the property after binding?

What is the difference between UpdateModel and TryUpdateModel and when do I need to use each?

EDIT:

I changed the name of the action to:

[HttpPost]
public ActionResult CreateApp()
{
   var application = new Application
   {
      ApplicationStateID = 1,
      SubmitterEmployeeNumber = "123456"
   };

   if (TryUpdateModel(application))
   {
      int success = 0;
   }
}

Here is my view:

<% using (Html.BeginForm("CreateApp", "Application")) {%>

TryUpdateModel still validates as false. I put in int success = 0; just to see if it will go into it but it doesn't.

Thanks, Brendan

+1  A: 
[HttpPost]
public ActionResult CreateApplication()
{
    var application = new Application 
    {
        SubmitterEmployeeNumber = "123456"
    };
    if (TryUpdateModel(application)) 
    {
        // The model is valid => submit values to the database
        return RedirectToAction("Success");
    }
    return View(application);
}

UPDATE: Due to many confusions in the comments section here's a full working example.

Model:

public class Application
{
    [Required]
    public int? ApplicationStateID { get; set; }

    [Required]
    public string SubmitterEmployeeNumber { get; set; }

    [Required]
    public string Foo { get; set; }

    [Required]
    public string Bar { get; set; }
}

Controller:

[HandleError]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        var application = new Application();
        return View(application);
    }

    [HttpPost]
    [ActionName("Index")]
    public ActionResult Create()
    {
        var application = new Application
        {
            ApplicationStateID = 1,
            SubmitterEmployeeNumber = "123456"
        };
        if (TryUpdateModel(application))
        {
            // success => update database, etc...
            return Content("yupee");
        }

        // failure => redisplay view to fix errors
        return View(application);
    }
}

View:

<% using (Html.BeginForm()) { %>
    <div>
        <%: Html.LabelFor(x => x.Foo) %>
        <%: Html.TextBoxFor(x => x.Foo) %>
        <%: Html.ValidationMessageFor(x => x.Foo) %>
    </div>

    <div>
        <%: Html.LabelFor(x => x.Bar) %>
        <%: Html.TextBoxFor(x => x.Bar) %>
        <%: Html.ValidationMessageFor(x => x.Bar) %>
    </div>

    <input type="submit" value="GO GO" />
<% } %>

Hope this clears things up.

Darin Dimitrov
The application object passed through to the CreateApplication action contains all my form values that were set. Doing it like you suggested will it still have all my form values that were set?
Brendan Vogt
Yes, that's what the `TryUpdateModel` method does. It uses the values POSTed in the request and populates the model. In addition it calls the validation.
Darin Dimitrov
I already have a CreateApplication() that I use to populate the view when it loads the first time. What do I do now?
Brendan Vogt
What first time? What view? What are you trying to do? Are you talking about action method overloading conflicts? In this case you need to use a different method name for your POST action.
Darin Dimitrov
When the view loads for the first time, then I have an CreateApplication action for the view (GET). When the user clicks the button they is a CreateApplication (POST).
Brendan Vogt
Then use different names or add a dummy parameter to cheat the compiler. You could also use the [`ActionName`](http://msdn.microsoft.com/en-us/library/system.web.mvc.actionnameattribute.aspx) attribute.
Darin Dimitrov
Check my update. After the user clicks the button, I want to set some properties, validate it as true, and then add to the database.
Brendan Vogt
The difference between `UpdateModel` and `TryUpdateModel` is that the first might throw an exception while the second returns a boolean indicating whether it succeeded. Did you try my example?
Darin Dimitrov
TryUpdateModel did not validate as true.
Brendan Vogt
This is what I did: public ActionResult CreateApplication(Application application) { application.SubmitterEmployeeNumber = "123456"; if (TryUpdateModel(application)) { } }. It's false, it's similar to yours?
Brendan Vogt
What you did is wrong and it is not similar to what I suggested. Look carefully at my code. The `application` in instantiated inside the action and not passed as parameter which is a fundamental difference. **Remove** the action parameter from the method signature or your model will never be valid.
Darin Dimitrov
OK I will remove it, but how would I change the action name? I thought the get and post had to be the same name as the view name? How would I then tell me the view to go into a different action when the button is clicked?
Brendan Vogt
No, they don't have to be the same. That's just a convention. In the view: `<% using (Html.BeginForm("SomeOtherActionName", "SomeController")) { %> ...` will generate the proper `<form>` tag.
Darin Dimitrov
Still not working. Check my update to my original post, I show how I changed it. Any ideas?
Brendan Vogt
You forgot to show how does your model look like and the view. Maybe there's some other property which fails to validate.
Darin Dimitrov
How would I see a list of errors? What exactly do you want to see?
Brendan Vogt
OK, it seems that I need to provide you with a full working example. Coming up.
Darin Dimitrov
I debugged it and saw what is happening. It's not retaining my form values. That is why it is failing. The only 2 values that are set are the ones that I set in the action. The others set in the form are lost. Why would this be? I am using a view model for this.
Brendan Vogt
Please see my example.
Darin Dimitrov
I have mine exactly the same. Can I send you my code?
Brendan Vogt
If you had the exactly same code then you have no problems, because this code works but send it if you will. Just make sure to strip all irrelevant parts. Don't expect me setting up a database or something like this in order to run your code.
Darin Dimitrov