views:

132

answers:

1

I have an mvc model class created and one of the properties is of type 'MyObject'. It also has a System.ComponentModel.DataAnnotations.StringLength attribute on it.

MyObject as implicit cast operators so it can essentially be used as a string:

public static implicit operator string(MyObject o){...}
public static implicit operator MyObject(string sValue){...}

Is this an asp mvc issue for some strange reason? I ask because I know in most cases the implicit cast works fine, I can for example assign that property to a string value and it works just fine.

Edit - Ok, I know why the error is occuring:
It's because the StringLength.IsValid() method takes an object as a parameter, so the cast is actually going from object to string, not from MyObject to string, so that explains why my implicit cast operator is not being called. But how to work around this?

This all worked fine until I put the System.ComponentModel.DataAnnotations.StringLength attribute on the property in my model, then when the view does a post from a submit button, I got the exception:

[InvalidCastException: Unable to cast object of type 'StrataSpot.Shared.Models.Email' to type 'System.String'.]
System.ComponentModel.DataAnnotations.StringLengthAttribute.IsValid(Object value) +34
System.Web.Mvc.d_1.MoveNext() +56 System.Web.Mvc.DefaultModelBinder.OnPropertyValidated(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, Object value) +203 System.Web.Mvc.DefaultModelBinder.BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor) +413
System.Web.Mvc.DefaultModelBinder.BindProperties(ControllerContext controllerContext, ModelBindingContext bindingContext) +90
System.Web.Mvc.DefaultModelBinder.BindComplexElementalModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Object model) +383
System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +1048
System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +280
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +257
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +109
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +314 System.Web.Mvc.Controller.ExecuteCore() +105 System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +39
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7
System.Web.Mvc.<>c
_DisplayClass8.b_4() +34 System.Web.Mvc.Async.<>c_DisplayClass1.b_0() +21 System.Web.Mvc.Async.<>c_DisplayClass81.<BeginSynchronous>b__7(IAsyncResult _) +12 System.Web.Mvc.Async.WrappedAsyncResult1.End() +59 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +44
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +7
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8678910 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

+1  A: 

You can't use [StringLength] for a property of a type other than String. If you want to duplicate the functionality, you can subclass StringLengthAttribute:

public class MyCoolAttribute : StringLengthAttribute {
  // constructor here

  public override bool IsValid(object value) {
    return base.IsValid((string)(value as MyObject));
  }
}

Then slap [MyCool] instead of [StringLength] on your property. Using a cast operator in this regard probably isn't the cleanest thing in the world; you should probably use ToString() or something similar instead. But the idea is the same.

Alternatively, if you don't want to subclass StringLengthAttribute, you can just delegate to a private StringLengthAttribute instance's IsValid() method instead.

Levi