asp.net-mvc – 使用MVC 4.0 Web Api的NewtonSoft json Contract
我正在尝试创建一个条件ContractResolver,以便我可以根据Web请求/控制器操作不同地控制序列化.
例如,在我的用户控制器中,我想序列化我的用户的所有属性,但是我可能只序列化基本类型的一些相关对象.但是,如果我去公司控制器,我想序列化公司的所有属性,但可能只是用户的原始属性(因此我不想使用数据注释或应该序列化函数. 因此,查看自定义的ContractResolver页面,我创建了自己的. 看起来像这样 public class IgnoreListContractResolver : DefaultContractResolver { private readonly Dictionary<string,List<string>> IgnoreList; public IgnoreListContractResolver(Dictionary<string,List<string>> i) { IgnoreList = i; } protected override IList<JsonProperty> CreateProperties(Type type,MemberSerialization memberSerialization) { List<JsonProperty> properties = base.CreateProperties(type,memberSerialization).ToList(); if(IgnoreList.ContainsKey(type.Name)) { properties.RemoveAll(x => IgnoreList[type.Name].Contains(x.PropertyName)); } return properties; } } 然后在GetUsers的web api控制器操作中,我这样做 public dynamic GetUsers() { List<User> Users = db.Users.ToList(); List<string> RoleList = new List<string>(); RoleList.Add("UsersInRole"); List<string> CompanyList = new List<string>(); CompanyList.Add("CompanyAccesses"); CompanyList.Add("ArchivedMemberships"); CompanyList.Add("AddCodes"); Dictionary<string,List<string>> IgnoreList = new Dictionary<string,List<string>>(); IgnoreList.Add("Role",RoleList); IgnoreList.Add("Company",CompanyList); GlobalConfiguration .Configuration .Formatters.JsonFormatter .SerializerSettings .ContractResolver = new IgnoreListContractResolver(IgnoreList); return new { List = Users,Status = "Success" }; } 因此,在调试时,我看到我的合同解析器运行并返回正确的属性,但返回浏览器的Json仍然包含我从列表中删除的属性的条目. 任何想法我缺少什么或如何进入webapi控制器中的Json序列化步骤. *更新** 谢谢 *更新2 ** public static string ToJson(this object o,Dictionary<string,List<string>> IgnoreList) { JsonSerializer js = JsonSerializer.Create(new Newtonsoft.Json.JsonSerializerSettings() { Formatting = Formatting.Indented,DateTimeZoneHandling = DateTimeZoneHandling.Utc,ContractResolver = new IgnoreListContractResolver(IgnoreList),ReferenceLoopHandling = ReferenceLoopHandling.Ignore }); js.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); var jw = new StringWriter(); js.Serialize(jw,o); return jw.ToString(); } 然后在MVC动作中我创建一个像这样的json字符串. model.jsonUserList = db.Users.ToList().ToJson(IgnoreList); 创建忽略列表的位置与我之前的帖子完全相同.我再次看到合同解析器运行并正确限制属性列表,但输出json字符串仍然包含所有内容(包括我从列表中删除的属性).这有帮助吗?我必须做错事,现在好像它不是MVC或web api框架.这可能与EF交互/代理/等有关.任何想法将不胜感激. 谢谢 *更新3 *** 消除过程和更彻底的调试使我意识到EF 5动态代理正在弄乱我的序列化和ContractResolver检查类型名称匹配.所以这是我更新的IgnoreListContractResolver.在这一点上,我只是在寻找更好的方法或者我做一些可怕的事情.我知道这是为了直接使用我的EF对象而不是DTO而跳过很多箍,但最后我发现这个解决方案非常灵活. public class IgnoreListContractResolver : CamelCasePropertyNamesContractResolver { private readonly Dictionary<string,memberSerialization).ToList(); string typename = type.Name; if(type.FullName.Contains("System.Data.Entity.DynamicProxies.")) { typename = type.FullName.Replace("System.Data.Entity.DynamicProxies.",""); typename = typename.Remove(typename.IndexOf('_')); } if (IgnoreList.ContainsKey(typename)) { //remove anything in the ignore list and ignore case because we are using camel case for json properties.RemoveAll(x => IgnoreList[typename].Contains(x.PropertyName,StringComparer.CurrentCultureIgnoreCase)); } return properties; } } 解决方法
我认为如果你使用Type而不是string作为忽略列表的键类型可能会有所帮助.因此,您可以避免命名问题(在不同的命名空间中具有相同名称的多个类型),并且您可以使用继承.我不熟悉EF5和代理,但我想代理类派生自你的实体类.因此,您可以检查
Type.IsAssignableFrom() 而不是仅仅检查typename是否是忽略列表中的键.
private readonly Dictionary<Type,List<string>> IgnoreList; protected override IList<JsonProperty> CreateProperties(Type type,MemberSerialization memberSerialization) { List<JsonProperty> properties = base.CreateProperties(type,memberSerialization).ToList(); // look for the first dictionary entry whose key is a superclass of "type" Type key = IgnoreList.Keys.FirstOrDefault(k => k.IsAssignableFrom(type)); if (key != null) { //remove anything in the ignore list and ignore case because we are using camel case for json properties.RemoveAll(x => IgnoreList[key].Contains(x.PropertyName,StringComparer.CurrentCultureIgnoreCase)); } return properties; } 然后必须像这样创建忽略列表(我还使用了短语法来创建列表和字典): var CompanyList = new List<string> { "CompanyAccesses","ArchivedMemberships","AddCodes" }; var IgnoreList = new Dictionary<Type,List<string>> { // I just replaced "Company" with typeof(Company) here: { typeof(Company),CompanyList } }; 请注意,如果您使用上面的代码,将typeof(object)作为忽略列表的第一个键添加将导致每次都匹配此条目,并且不会使用任何其他条目!发生这种情况是因为对象类型的变量可以从其他每种类型分配. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – DOM异常:INVALID_CHARACTER_ERR(5)[已关闭]
- asp.net-core – “如果从deploy文件夹运行,则需要”库’ho
- asp.net – 动态地将ASP控件添加到表中
- 如何在asp.net中使用JSON和JQuery从WebMethod返回DataTable
- asp.net-mvc – 使用OWIN进行基于区域的身份验证
- asp.net-mvc – 如何删除SimpleMembership用户?
- asp.net-mvc – 动作命名约定
- 线程是否在ASP.Net中的请求之间重用?
- asp.net repeater手写分页实例代码
- asp.net – 渗透测试人员说.ASPXAUTH cookie是不安全的并且
- asp.net-core-mvc – “:exists”在路由模板上做
- asp.net-mvc – 从IIS重写http到https的URL重写不
- 实体框架 – WebApi OData:$filter’any’或’a
- 代码翻译:ASP.NET Server.Transfer in PHP
- asp.net-mvc-3 – MVC 3 knockoutjs:在使用Edit
- Godaddy ASP.NET会员数据库困境
- ASP.NET vnext和打开数据库
- asp.net-mvc-4 – 无法让ASP.NET 4 Web API返回状
- asp.net-mvc-3 – Razor查看if语句是否正确
- asp.net – 为自定义UserControl提供呈现HTML中的