Shadow_boi
Shadow_boi

Reputation: 2198

asp.net mvc3 Bind Exclude on properties does not work

I have a class, which has 8 properties / 8 columns in DB. In the Edit page, I want to exclude the AddedDate and UserID fields. When a user edits a voucher, he can't overwrite the AddedDate or UserID values in the DB.

public class Voucher
{
    public int ID { get; set; }
    public string Title { get; set; }
    public string SiteName { get; set; }
    public string DealURL { get; set; }
    public DateTime AddedDate { get; set; }
    public DateTime? ExpirationDate { get; set; }
    public string VoucherFileURL { get; set; }
    public Guid UserID { get; set; }
}

Here is what I have for Edit controller:

// POST: /Voucher/Edit/5

[HttpPost]
public ActionResult Edit([Bind(Exclude = "AddedDate")]Voucher voucher)
{
    if (ModelState.IsValid)
    {

        db.Entry(voucher).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(voucher);
}

On Edit page, when I click on submit, I got the following error:

System.Data.SqlServerCe.SqlCeException: An overflow occurred while converting to datetime.

Seems like the AddedDate didn't get excluded from the voucher object and triggered the error.

Would you please let me know how to fix it? Thanks!

(it is an updated version of asp.net mvc3 UpdateModel exclude properties is not working, I will go with another approach)

Upvotes: 2

Views: 2493

Answers (1)

Darin Dimitrov
Darin Dimitrov

Reputation: 1039548

Never use your domain entities as action arguments and never pass your domain entities to your views. I would recommend you to use view models. In the view model you will include only the properties that you want to be bound from the view. The view model is a class that's specifically tailored to the requirements of a given view.

public class VoucherViewModel
{
    public int ID { get; set; }
    public string Title { get; set; }
    public string SiteName { get; set; }
    public string DealURL { get; set; }
    public DateTime? ExpirationDate { get; set; }
    public string VoucherFileURL { get; set; }
}

and then:

[HttpPost]
public ActionResult Edit(VoucherViewModel model)
{
    // TODO: if the view model is valid map it to a model
    // and pass the model to your DAL
    // To ease the mapping between your models and view models
    // you could use a tool such as AutoMapper: http://automapper.org/
    ...
}

UPDATE:

In the comments section @Rick.Anderson-at-Microsoft.com points out that while I have answered your question I haven't explained where the problem comes from.

The thing is that DateTime is a value type meaning it will always have a value. The [Bind(Exclude = "AddedDate")] works perfectly fine and it does what it is supposed to do => it doesn't bind the AddedDate property from the request. As a consequence the property will have its default value which for a DateTime field is 1/1/0001 12:00:00 AM and when he attempts to save this in SQL Server it blows because SQL Server doesn't support such format.

Upvotes: 4

Related Questions