Search code examples
vb.netcastingwebmethod

Why does this non-primitive type conversion fail in webmethod parameter?


I have created a custom class "TestStr" that is intended to be interchangeable with primitive strings:

Public Class TestStr
    Public ReadOnly Property Value As String
    Public Sub New(ByVal s As String)
        Value = s
    End Sub
    Public Shared Widening Operator CType(ByVal s As TestStr) As Long
        Return s.Value
    End Operator
    Public Shared Narrowing Operator CType(ByVal s As String) As TestStr
        Return New TestStr(s)
    End Operator
End Class

And in practice, this appears to be working fine in most cases:

Dim x As TestStr = "hey"
Dim y As String = x

However, when I have a TestStr as a parameter in a webmethod like so:

<WebMethod(True), ScriptMethod(ResponseFormat:=ResponseFormat.Json, UseHttpGet:=True)>
Public Shared Function GetClientUserRecord(ByVal ClientUserId As TestStr) As String

The web method call fails and I get this error in the browser console:

Cannot convert object of type "System.String" to type "my.mamespace.TestStr"
   at System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeInternal(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object\u0026 convertedObject)
   at System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeMain(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object\u0026 convertedObject)
   at System.Web.Script.Services.WebServiceMethodData.StrongTypeParameters(IDictionary`2 rawParams)
   at System.Web.Script.Services.WebServiceMethodData.CallMethodFromRawParams(Object target, IDictionary`2 parameters)
   at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData methodData, IDictionary`2 rawParams)
   at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.InvalidOperationException"}

Is there something I'm doing wrong in the class setup, or is this not supported by VB.NET? For reference, I'm using .NET Framework 4.6. The main intention of this is to make TestStr's constructor automatically handle null/empty strings, and also trim the user's input string, so the webmethod can be called with the parameter " test " and I won't need to do manual string trimming in every webmethod with user input.


Solution

  • ASP.NET MVC, and apparently web methods, too, will use the type converter defined for your custom type to convert the input to that type.

    The type converter for System.Uri is probably a good example. For a simple wrapper like TestStr, you would need to do even less.