views:

708

answers:

2

I have a double-precision floating point field in my database that stores seconds past midnight. I have code in c# that can convert this number to the form HH:MM:SS.ffffff, where f is fractions of a second. I also have code that can parse this back into a double.

What I would like to do is modify the stock binder object in ASP.NET MVC so that it uses MY parsing and ToString() methods instead of the ones it would normally use from the double type, without having to write a complete custom binder.

Can I write a couple of extension methods in c#, or use a couple of well-placed attributes to let the binder object know about my parsing and ToString() methods?

Here is some more clarification.

if I provide a model such as a Linq to SQL class to the view, MVC can automatically wire up my fields to the underlying data model, provided I use the same names for the controls in my view as I have used in my data model. If I post my MVC view back to a controller method, I can write the user's changes back to the database by calling the UpdateModel method on my Controller class. I don't have to worry about wiring up my specific fields from the FormCollection to my Linq to SQL data class, because the binder has done that for me already.

I assume that, in order for the binder to work this magic on an ordinary numeric double, that it must first parse the input from the user (probably by calling double.parse), and pass this to the Linq to SQL class so that it can update the database.

I need to use my own custom parser, instead of the one that comes with the double data type, for one of the fields in my model. I don't want to have to assume responsibility for the remaining fields.

A: 

Is it absolutely necessary to have the name be .ToString()? It is easy if for example .ToCustomString() is acceptable:

public static class DoubleExtensions
{
 public static string ToCustomString(this double d)
 {
  return "my own";
 }
}
Tomas Lycken
In what context is it used? Where is the text outputted (in the way you want to change)?
Tomas Lycken
OK, but how do I tell the MVC binder to use this method instead of its own?Actually, I'm more concerned about parsing the user's input. I can always provide formatting in the view for display.
Robert Harvey
Please provide some sample code where the .ToString() method will be called, where you want to change the output. Without any sample code, it is very hard to help...
Tomas Lycken
+1  A: 

This is a naive, quick and dirty example, but if you decide to go the model binder route, try something like:

// This goes in global.asax
ControllerBuilder.Current.SetControllerFactory(new ControllerFactory());
ModelBinders.Binders.Add(typeof(CustomDateType), new CustomDateBinder());

......

public class CustomDateType
{
    public CustomDateType(string value)
    {
    }

    public string GetText()
    {
     // I do fancy stuff
     throw new NotImplementedException();
    }
    public decimal? GetValue()
    {
     // I do fancy stuff
     throw new NotImplementedException();
    }
}

public class CustomDateBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        try
     {
      string doubleDateValue = GetAttemptedValue(bindingContext);

      if (doubleDateValue == "")
      {
       return null;
      }

      return new CustomDateType(doubleDateValue);
     }
     catch (Exception ex)
     {
      string message = string.Format("Unable to locate a valid value for query string parameter '{0}'",
                                 bindingContext.ModelName);
      throw new ApplicationException(message, ex);
     }
    }

    private static string GetAttemptedValue(ModelBindingContext bindingContext)
    {
     ValueProviderResult value = bindingContext.ValueProvider[bindingContext.ModelName];
     return value == null ? string.Empty : value.AttemptedValue;
    }
 }
Matt Hinze
Looks good, thanks. I will try it.
Robert Harvey