如何在ASP.NET MVC ValueProvider中使用ServiceStack.Text进行Json反序列化

时间:2014-08-06 00:09:17

标签: asp.net-mvc json servicestack-text value-provider

如何在控制器方法参数的值绑定期间使用ServiceStack.Text Json序列化程序对ASP.NET MVC请求中的字符串进行反序列化?

1 个答案:

答案 0 :(得分:1)

我最终不得不写自定义课程。要使用下面的工厂,请使用以下代码更新您的Application_Start

ValueProviderFactories.Factories.Remove( ValueProviderFactories.Factories.OfType< JsonValueProviderFactory >().FirstOrDefault() );
ValueProviderFactories.Factories.Add( new JsonServiceStackValueProviderFactory() )

这对我有用:

public sealed class JsonServiceStackValueProviderFactory: ValueProviderFactory
{
    public override IValueProvider GetValueProvider( ControllerContext controllerContext )
    {
        if( controllerContext == null )
            throw new ArgumentNullException( "controllerContext" );

        var jsonData = GetDeserializedObject( controllerContext );
        if( jsonData == null )
            return null;

        var backingStore = new Dictionary< string, object >( StringComparer.OrdinalIgnoreCase );
        AddToBackingStore( backingStore, String.Empty, jsonData );
        return new DictionaryValueProvider< object >( backingStore, CultureInfo.CurrentCulture );
    }

    private static object GetDeserializedObject( ControllerContext controllerContext )
    {
        if( !controllerContext.HttpContext.Request.ContentType.StartsWith( "application/json", StringComparison.OrdinalIgnoreCase ) )
        {
            // not JSON request
            return null;
        }

        var reader = new StreamReader( controllerContext.HttpContext.Request.InputStream );
        var bodyText = reader.ReadToEnd();
        if( String.IsNullOrEmpty( bodyText ) )
        {
            // no JSON data
            return null;
        }

        var firstNonEmptyChar = GetFirstNonEmptyChar( bodyText );

        if( firstNonEmptyChar == '[' )
        {
            var jsonData = JsonSerializer.DeserializeFromString< List< Dictionary< string, object > > >( bodyText );
            return jsonData;
        }
        else
        {
            var jsonData = JsonSerializer.DeserializeFromString< Dictionary< string, object > >( bodyText );
            return jsonData;
        }
    }

    private static void AddToBackingStore( Dictionary< string, object > backingStore, string prefix, object value )
    {
        var d = value as IDictionary< string, object >;
        if( d != null )
        {
            foreach( var entry in d )
            {
                AddToBackingStore( backingStore, MakePropertyKey( prefix, entry.Key ), entry.Value );
            }
            return;
        }

        var l = value as IList;
        if( l != null )
        {
            for( var i = 0; i < l.Count; i++ )
            {
                AddToBackingStore( backingStore, MakeArrayKey( prefix, i ), l[ i ] );
            }
            return;
        }

        // primitive
        backingStore[ prefix ] = value;
    }

    private static string MakeArrayKey( string prefix, int index )
    {
        return prefix + "[" + index.ToString( CultureInfo.InvariantCulture ) + "]";
    }

    private static string MakePropertyKey( string prefix, string propertyName )
    {
        return ( String.IsNullOrEmpty( prefix ) ) ? propertyName : prefix + "." + propertyName;
    }

    private static char? GetFirstNonEmptyChar( string @string )
    {
        for( var i = 0; i < @string.Length; i++ )
        {
            if( !char.IsWhiteSpace( @string[ i ] ) )
                return @string[ i ];
        }
        return new char?();
    }
}