Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc Json.Net:Html帮助程序方法未重新生成_Asp.net Mvc_Angularjs_Json.net - Fatal编程技术网

Asp.net mvc Json.Net:Html帮助程序方法未重新生成

Asp.net mvc Json.Net:Html帮助程序方法未重新生成,asp.net-mvc,angularjs,json.net,Asp.net Mvc,Angularjs,Json.net,我遇到了一个问题,我创建的ASP.NET MVC html帮助程序方法在每次调用时都没有“重新生成” helper方法的目的是创建要在angularjs框架中使用的Javascript对象。例如,这里有一个使用helper方法的代码段(从html页面的脚本标记中调用): Model是一个具有多种属性的类的实例,但我只希望FirstName、LastName、ID和Role被序列化为一个javascript对象 ToJavascript()助手方法在statis类中定义如下: public

我遇到了一个问题,我创建的ASP.NET MVC html帮助程序方法在每次调用时都没有“重新生成”

helper方法的目的是创建要在angularjs框架中使用的Javascript对象。例如,这里有一个使用helper方法的代码段(从html页面的脚本标记中调用):

Model是一个具有多种属性的类的实例,但我只希望FirstName、LastName、ID和Role被序列化为一个javascript对象

ToJavascript()助手方法在statis类中定义如下:

   public static HtmlString ToJavascript( this HtmlHelper helper, object toConvert, string[] includedFields = null, Formatting formatting = Formatting.Indented, ReferenceLoopHandling loopHandling = ReferenceLoopHandling.Ignore )
    {
        using( var stringWriter = new StringWriter() )
        using( var jsonWriter = new JsonTextWriter( stringWriter ) )
        {
            var serializer = new JsonSerializer()
            {
                // Let's use camelCasing as is common practice in JavaScript
                ContractResolver = new SpecificFieldsResolver( includedFields ),
                Formatting = formatting,
                ReferenceLoopHandling = loopHandling,
            };

            // We don't want quotes around object names
            jsonWriter.QuoteName = false;
            serializer.Serialize( jsonWriter, toConvert );

            return new HtmlString( stringWriter.ToString() );
        }
    }
public class SpecificFieldsResolver : CamelCasePropertyNamesContractResolver
{
    private string[] _included;

    public SpecificFieldsResolver( string[] included )
    {
        _included = included;
    }

    protected override JsonProperty CreateProperty( MemberInfo member, MemberSerialization memberSerialization )
    {
        JsonProperty prop = base.CreateProperty( member, memberSerialization );

        bool inclField = ( _included == null )
            || _included.Contains( member.Name, StringComparer.CurrentCultureIgnoreCase );

        prop.ShouldSerialize = obj => inclField;

        return prop;
    }
}
这将利用Json.NET进行实际的序列化

Json.NET的许多很酷的特性之一是,它允许您动态地定义哪些字段被序列化。这就是SpecificFieldsResolver所做的。我将其定义如下:

   public static HtmlString ToJavascript( this HtmlHelper helper, object toConvert, string[] includedFields = null, Formatting formatting = Formatting.Indented, ReferenceLoopHandling loopHandling = ReferenceLoopHandling.Ignore )
    {
        using( var stringWriter = new StringWriter() )
        using( var jsonWriter = new JsonTextWriter( stringWriter ) )
        {
            var serializer = new JsonSerializer()
            {
                // Let's use camelCasing as is common practice in JavaScript
                ContractResolver = new SpecificFieldsResolver( includedFields ),
                Formatting = formatting,
                ReferenceLoopHandling = loopHandling,
            };

            // We don't want quotes around object names
            jsonWriter.QuoteName = false;
            serializer.Serialize( jsonWriter, toConvert );

            return new HtmlString( stringWriter.ToString() );
        }
    }
public class SpecificFieldsResolver : CamelCasePropertyNamesContractResolver
{
    private string[] _included;

    public SpecificFieldsResolver( string[] included )
    {
        _included = included;
    }

    protected override JsonProperty CreateProperty( MemberInfo member, MemberSerialization memberSerialization )
    {
        JsonProperty prop = base.CreateProperty( member, memberSerialization );

        bool inclField = ( _included == null )
            || _included.Contains( member.Name, StringComparer.CurrentCultureIgnoreCase );

        prop.ShouldSerialize = obj => inclField;

        return prop;
    }
}
让我困惑的是调用CreateProperty()的方式。具体地说,对于被序列化的每种类型的对象,它似乎只被调用一次

这是一个问题,因为在另一个cshtml文件中,我有另一个对ToJavascript()的调用,该调用试图序列化相同类型的对象,但要从序列化中输出不同的字段:

var app = angular.module( "app2Name", ["ui.bootstrap"] );

app.controller( 'app2Ctrl', function( $scope ) {
    $scope.model = @Html.ToJavascript( Model, new string[] { "FirstName", "LastName", "ID", "Role", "Category", "VoterID" } );
} );
Category和VoterID也是有效的类字段。但是ToJavascript()并没有将它们序列化。相反,它只序列化在对ToJavascript()的第一次调用中定义的字段……即使该调用发生在不同的cshtml文件中。这就好像SpecificFieldsResolver记住了它创建的JsonProperty对象一样

想法

更新

Thanx感谢dbc准确诊断错误并提出解决方案。我稍微修改了一下,因为我在几个解析器中依赖Json.NET的驼峰大小写名称解析:

public class CamelCaseNameMapper : CamelCasePropertyNamesContractResolver
{
    public string ToCamelCase( string propertyName )
    {
        return ResolvePropertyName( propertyName );
    }
}

public class MaoDefaultContractResolver : DefaultContractResolver
{
    private CamelCaseNameMapper _mapper = new CamelCaseNameMapper();

    protected override string ResolvePropertyName( string propertyName )
    {
        return _mapper.ToCamelCase( propertyName );
    }

}

现在,每个解析器,例如my SpecificFieldsResolver,它派生自MaoDefaultContractResolver,自动继承camel大小写,但避免了dbc识别的缓存问题。

这似乎是一个错误。它的基类有两个构造函数:a和一个版本(刚刚在Json.NET 7.0中过时)。此参数具有以下含义:

共享缓存

  • 类型:System.Boolean

    如果设置为true,则
    DefaultContractResolver
    将使用与相同类型的其他解析程序共享的缓存。共享缓存将显著提高多个解析器实例的性能,因为昂贵的反射只会发生一次。如果假定解析器的不同实例产生不同的结果,则此设置可能会导致意外行为。当设置为false时,强烈建议将
    DefaultContractResolver
    实例与
    JsonSerializer
    一起重用

默认值为
false

不幸的是,for
CamelCasePropertyNamesContractResolver
将该值设置为
true

public class CamelCasePropertyNamesContractResolver : DefaultContractResolver
{
    public CamelCasePropertyNamesContractResolver()
#pragma warning disable 612,618
        : base(true)
#pragma warning restore 612,618
    {
        NamingStrategy = new CamelCaseNamingStrategy
        {
            ProcessDictionaryKeys = true,
            OverrideSpecifiedNames = true
        };
    }
}
此外,没有第二个构造函数具有
shareCache
选项。这会中断您的
SpecificFieldsResolver

作为一种解决方法,您可以从
DefaultContractResolver
派生解析器,并使用它进行名称映射:

public class IndependentCamelCasePropertyNamesContractResolver : DefaultContractResolver
{
    public IndependentCamelCasePropertyNamesContractResolver()
        : base()
    {
        NamingStrategy = new CamelCaseNamingStrategy
        {
            ProcessDictionaryKeys = true,
            OverrideSpecifiedNames = true
        };
    }    
}

public class SpecificFieldsResolver : IndependentCamelCasePropertyNamesContractResolver
{
    // Remainder unchanged
}
请注意,如果您使用的是9.0之前的Json.NET版本,
CamelCaseNamingStrategy
不存在。相反,可以使用嵌套的kludge
CamelCasePropertyNamesContractResolver
映射名称:

public class IndependentCamelCasePropertyNamesContractResolver : DefaultContractResolver
{
    class CamelCaseNameMapper : CamelCasePropertyNamesContractResolver
    {
        // Purely to make the protected method public.
        public string ToCamelCase(string propertyName)
        {
            return ResolvePropertyName(propertyName);
        }
    }
    readonly CamelCaseNameMapper nameMapper = new CamelCaseNameMapper();

    protected override string ResolvePropertyName(string propertyName)
    {
        return nameMapper.ToCamelCase(propertyName);
    }
}

这似乎是一个错误。它的基类有两个构造函数:a和一个版本(刚刚在Json.NET 7.0中过时)。此参数具有以下含义:

共享缓存

  • 类型:System.Boolean

    如果设置为true,则
    DefaultContractResolver
    将使用与相同类型的其他解析程序共享的缓存。共享缓存将显著提高多个解析器实例的性能,因为昂贵的反射只会发生一次。如果假定解析器的不同实例产生不同的结果,则此设置可能会导致意外行为。当设置为false时,强烈建议将
    DefaultContractResolver
    实例与
    JsonSerializer
    一起重用

默认值为
false

不幸的是,for
CamelCasePropertyNamesContractResolver
将该值设置为
true

public class CamelCasePropertyNamesContractResolver : DefaultContractResolver
{
    public CamelCasePropertyNamesContractResolver()
#pragma warning disable 612,618
        : base(true)
#pragma warning restore 612,618
    {
        NamingStrategy = new CamelCaseNamingStrategy
        {
            ProcessDictionaryKeys = true,
            OverrideSpecifiedNames = true
        };
    }
}
此外,没有第二个构造函数具有
shareCache
选项。这会中断您的
SpecificFieldsResolver

作为一种解决方法,您可以从
DefaultContractResolver
派生解析器,并使用它进行名称映射:

public class IndependentCamelCasePropertyNamesContractResolver : DefaultContractResolver
{
    public IndependentCamelCasePropertyNamesContractResolver()
        : base()
    {
        NamingStrategy = new CamelCaseNamingStrategy
        {
            ProcessDictionaryKeys = true,
            OverrideSpecifiedNames = true
        };
    }    
}

public class SpecificFieldsResolver : IndependentCamelCasePropertyNamesContractResolver
{
    // Remainder unchanged
}
请注意,如果您使用的是9.0之前的Json.NET版本,
CamelCaseNamingStrategy
不存在。相反,可以使用嵌套的kludge
CamelCasePropertyNamesContractResolver
映射名称:

public class IndependentCamelCasePropertyNamesContractResolver : DefaultContractResolver
{
    class CamelCaseNameMapper : CamelCasePropertyNamesContractResolver
    {
        // Purely to make the protected method public.
        public string ToCamelCase(string propertyName)
        {
            return ResolvePropertyName(propertyName);
        }
    }
    readonly CamelCaseNameMapper nameMapper = new CamelCaseNameMapper();

    protected override string ResolvePropertyName(string propertyName)
    {
        return nameMapper.ToCamelCase(propertyName);
    }
}

哇!在这里,我认为我的问题太模糊,也太没有记录,无法给出答案。非常感谢你!你的分析完全正确。我对您的解决方案采取了稍微不同的方法,因为我在几个解析器中使用了驼峰案例解析功能。你知道这个限制是否被报告给了Json.NET吗?@MarkOlbert-很乐意帮忙。不,我不知道是否有报道。非常感谢你的解释。在这里遇到了同样的问题,只花了一天的时间就解决了问题,只花了一个小时就解决了CamelCase构造函数的问题。至少我们有了资料来源。哇!在这里,我认为我的问题太模糊,也太没有记录,无法给出答案。非常感谢你!你的分析完全正确。我对您的解决方案采取了稍微不同的方法,因为我在几个解析器中使用了驼峰案例解析功能。你知道这个限制是否上报给Jso了吗