gpt4 book ai didi

asp.net-mvc - Json.Net:Html Helper Method 未重新生成

转载 作者:行者123 更新时间:2023-12-02 08:27:33 25 4
gpt4 key购买 nike

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

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

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

app.controller( 'appCtrl', function( $scope ) {
$scope.model = @Html.ToJavascript( Model, new string[] { "FirstName", "LastName", "ID", "Role" } );
} );

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() );
}
}

这利用 Json.NET 进行实际的序列化。

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

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 对象。

想法?

更新

感谢 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 );
}

}

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

最佳答案

这似乎是 CamelCasePropertyNamesContractResolver 的错误。 .它的基类 DefaultContractResolver , 有两个构造函数:一个 parameterless constructor , 和 DefaultContractResolver (Boolean)版本(刚刚在 Json.NET 7.0 中过时)。该参数含义如下:

shareCache

  • Type: System.Boolean

    If set to true the DefaultContractResolverwill use a cached shared with other resolvers of the same type. Sharing the cache will significantly improve performance with multiple resolver instances because expensive reflection will only happen once. This setting can cause unexpected behavior if different instances of the resolver are suppose to produce different results. When set to false it is highly recommended to reuse DefaultContractResolver instances with the JsonSerializer.

默认为 false

不幸的是,default constructor对于 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 派生解析器并使用 CamelCaseNamingStrategy进行名称映射:

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 不存在。相反,可以使用嵌套的 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);
}
}

关于asp.net-mvc - Json.Net:Html Helper Method 未重新生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30740734/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com