Связывание моделей MVC + форматирование - PullRequest
3 голосов
/ 02 марта 2011

В моем приложении MVC есть модель (Northwind), у которой есть свойство UnitPrice:

public class Product { 
    public decimal UnitPrice { get; set; }
}

На мой взгляд, я хочу отобразить это как валюту {0: C}. Я пытался использовать DataAnnotations DisplayFormatAttribute: http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.displayformatattribute.aspx

Это хорошо работало для отображения, но когда я пытаюсь POST, я не могу отправить, потому что он не в правильном формате. Если я удалю $, то это позволит мне.

Можно ли как-нибудь игнорировать формат при попытке проверки?

Ответы [ 2 ]

4 голосов
/ 02 марта 2011

Вы можете написать пользовательский механизм связывания для типа Product и вручную проанализировать значение. Вот как вы могли бы продолжить:

Модель:

public class Product
{
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:C}")]
    public decimal UnitPrice { get; set; }
}

Контроллер:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new Product { UnitPrice = 10.56m });
    }

    [HttpPost]
    public ActionResult Index(Product product)
    {
        if (!ModelState.IsValid)
        {
            return View(product);
        }
        // TODO: the model is valid => do something with it
        return Content("Thank you for purchasing", "text/plain");
    }
}

Вид:

@model AppName.Models.Product
@using (Html.BeginForm())
{
    @Html.LabelFor(x => x.UnitPrice)
    @Html.EditorFor(x => x.UnitPrice)
    @Html.ValidationMessageFor(x => x.UnitPrice)
    <input type="submit" value="OK!" />
}

Модель Binder (вот где произойдет магия):

public class ProductModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var price = bindingContext.ValueProvider.GetValue("unitprice");
        if (price != null)
        {
            decimal p;
            if (decimal.TryParse(price.AttemptedValue, NumberStyles.Currency, null, out p))
            {
                return new Product
                {
                    UnitPrice = p
                };
            }
            else
            {
                // The user didn't type a correct price => insult him
                bindingContext.ModelState.AddModelError("UnitPrice", "Invalid price");
            }
        }
        return base.BindModel(controllerContext, bindingContext);
    }
}

Регистрация модели связующего в Application_Start:

ModelBinders.Binders.Add(typeof(Product), new ProductModelBinder());
0 голосов
/ 02 марта 2011

Если вы хотите, чтобы форматирование применялось только на дисплее, установите для ApplyFormatInEditMode значение false.

...