views:

131

answers:

3

I'm using ASP.NET MVC 2 and here's the issue. My View Model looks something like this. It includes some fields which are edited by the user and others which are used for display purposes. Here's a simple version

public class MyModel 
{
    public decimal Price { get; set; } // for view purpose only

    [Required(ErrorMessage="Name Required")]
    public string Name { get; set; }
}

The controller looks something like this:

public ActionResult Start(MyModel rec)
{
    if (ModelState.IsValid)
    {
        Repository.SaveModel(rec);
        return RedirectToAction("NextPage");
    }
    else
    {
        // validation error
        return View(rec);
    }
}

The issue is when there's a validation error and I call View(rec), I'm not sure the best way to populate my view model with the values that are displayed only.

The old way of doing it, where I pass in a form collection, I would do something like this:

public ActionResult Start(FormCollection collection)
{
    var rec = Repository.LoadModel();
    UpdateModel(rec);
    if (ModelState.IsValid)
    {
        Repository.SaveModel(rec);
        return RedirectToAction("NextPage");
    }
    else
    {
        // validation error
        return View(rec);
    }
}

But doing this, I get an error on UpdateModel(rec): The model of type 'MyModel' could not be updated.

Any ideas?

A: 

Your Price member setter (probably) shouldn't be public, you may want to consider loading the price from where ever it's stored in the model.

The other thing would be when rendering the view don't render the Price with a text box (or other input type).

public class MyModel 
{


    public decimal Price 
    { 
        get
        { 
            return //get the value from something
        }
    } // for view purpose only

    [Required(ErrorMessage="Name Required")]
    public string Name { get; set; }
}
confusedGeek
A: 

Using a strong type View

If you' use a strong type view this should work out of the box:

ViewPage<MyModel>

Your fields should be displayed as:

<%= Html.TextBoxFor(m => m.Name) %>

You shouldn't display read-only properties in editable fields anyway. When you'd redisplay the invalid view and providing the passed in model object instance in your controller action, your values should be populated in your textbox (or string only containers) as expected.

I don't think you should have any problems with Price property this way, but just in case have you tried using this controller action declaration:

public ActionResult Start([Bind(Exclude = "Price")]MyModel rec)
{
    // ...
}
Robert Koritnik
+2  A: 

I figured this one out. If you call UpdateModel and there's a validation error, it's going to throw an exception. The way around this is call TryUpdateModel instead.

Keltex