views:

43

answers:

2

So I'm looking into writing some custom MVC extensions and the first one I'm attempting to tackle is a FormattedTextBox to handle things such as currency, dates, and times. I have the rendering of it working perfectly, formatting it, working with strong types and everything all golden. However, the problem I'm now running into is cleaning up the formatted stuff when the page posts the data back.

Take for example, a currency format. Let's use USD for these examples. When an object has a property as a decimal, the value would be 79.95. Your edit view would be something like:

<%= Html.FormattedTextBox(model => Model.Person.HourlyWage, "{0:C}") %>

This is all well and good for the GET request, but upon POST, the value is going to be $79.95, which when you assign to that decimal, gets unhappy very quickly and ends up shoving a 0 in there.

So my question is, how do I get code working somewhere to work with that value before the MVC Framework goes and starts shoving it back into my ViewModel? I'd much rather this be done server-side than client-side.

Thanks!!

+1  A: 

One solution would be to write a custom model binder which will be able to convert bind $79.95 to a decimal field in your model. Another solution is to do it on the client side. In a jQuery form.submit handler you could modify the values of the input fields to be posted.

Darin Dimitrov
Doing it this way, then my controller needs to be aware of implementation inside of my view's "control", right? I don't like that...
Jaxidian
Not your controller, your model binder, which is their purpose by the way. But if you don't like it you still have the javascript solution.
Darin Dimitrov
Marking this as the answer between the two simply because it was posted first. Both give the same solution - wish I could split credit somehow since Branislav posted a code sample to go with it.
Jaxidian
+1  A: 

You can use custom Model Binders to shove the posted data into an object.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(
    [ModelBinder(typeof(YourModelBinderAttribute))]YourClass obj)
{
  // your code here

  return View();
}

public class MessageModelBinderAttribute : IModelBinder
{
    #region IModelBinder Members

    public object BindModel(
        ControllerContext controllerContext, 
        ModelBindingContext bindingContext)
    {
        YourClass obj = new YourClass();

        ValueProviderResult result;
        if (bindingContext.ValueProvider.TryGetValue(
            "YourPostedInputName", out result))
        {
            obj.Price = result.AttemptedValue;
        }

        return message;
    }

    #endregion
}
Branislav Abadjimarinov
Doing it this way, then my controller needs to be aware of implementation inside of my view's "control", right? I don't like that...
Jaxidian
Your conroller will not be aware, your model binder will be. But still it is better than having the parameters in the controller's action.
Branislav Abadjimarinov