I have field for decimal price, for instance 20,00 and want to write my own validation message instead of default "The field Price must be a number". As I soon have understood, I get validation error because of comma in number, view interprets it as a string. So that I should fix this as well.
I found this solution written by @DarinDimitrov, I write custom model binder
public class PriceModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var displayFormat = bindingContext.ModelMetadata.DisplayFormatString;
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (!string.IsNullOrEmpty(displayFormat) && value != null)
{
decimal price;
if (decimal.TryParse(value.AttemptedValue, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out price))
{
return price;
}
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Неверный формат числа");
}
return base.BindModel(controllerContext, bindingContext);
}
}
I also add it in Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ModelBinders.Binders.Add(typeof(decimal), new PriceModelBinder());
}
Besides I add to web.config <globalization culture="ru-RU" uiCulture="ru-RU" />
in <system.web>
. When I place a breakpoint and try to add entity from view, but nothing changes, I get the same default error string. Moreover breakpoint wasn't caught.
After a little more search I found that model binder works only when POST-method is calling, but my method is already POST as I add entity. I tried to add check in controller ModelState.IsValid
, but it has no effect, as form wasn't sent to server.
Here my ideas is over, maybe someone can help. Down I write parts of model, view and controller.
public class ServiceDto
{
//other properties
[Display(Name = "Цена"), DataType(DataType.Currency, ErrorMessage = "Неверный формат числа")]
[Required(ErrorMessage = "Цена услуги обязательна")]
public decimal Price { get; set; }
}
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
public class OperatorController : Controller
{
[HttpPost]
public ActionResult CreateService(ServiceDto serviceDto)
{
//mapping here
_unitOfWork.Services.Create(service);
_unitOfWork.Save();
return RedirectToAction("Index");
}
}
UPDATE
I add this js script to view after all other ones, but nothing changed.
<script src="/Scripts/jquery-1.10.2.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
<script src="/Scripts/bootstrap.js"></script>
<script src="/Scripts/respond.js"></script>
<script type="text/javascript">
$.validator.methods.number = function (value, element) {
return this.optional(element) || /^-?(?:d+|d{1,3}(?:[s.,]d{3})+)(?:[.,]d+)?$/.test(value);
};
</script>
Maybe this script is not being executed? Sorry, I mostly work with backend, and if problem is connected with js, it is dark forest for me.