MVC3基本控制器崩溃,相同代码在继承的控制器中工作
本文关键字:控制器 继承 代码 工作 崩溃 MVC3 | 更新日期: 2023-09-27 18:20:04
背景
.NET 4、C#、MVC3,使用JsonFx对数据进行序列化和反序列化。基本控制器已扩展为拦截所有请求并执行以下操作:
- 从远程服务器获取一些JSON
- 基于传入的键(英雄、正文、页脚)运行LINQ查询
- 将通用模型返回到视图中
当在继承自基本控制器的控制器中运行时,此代码运行良好,但当放置在基本控制器中并从继承的控制器调用时,我会得到以下错误:
Unable to cast object of type 'System.Linq.Expressions.ConstantExpression' to type 'System.Linq.Expressions.ParameterExpression'.
这是一条令人反感的线路:
var queryHero = heroModel.ArrayItems().Where(o => o.DisplayName == keyHero);
问题
如何避免在基本控制器中出现类型错误?这是在继承的控制器中运行良好的相同代码。
谢谢你抽出时间。
完整代码
public models.GenericPageModel GetGenericPageContent(string keyHero, string keyBody, string keyFooter)
{
try
{
// get content "tables"
var heroContent = GetJson("Page_Section_Hero_Content");
var bodyContent = GetJson("Page_Section_Body_Content");
var footerContent = GetJson("Page_Section_Footer_Content");
// new reader
var reader = new JsonReader(new DataReaderSettings(new DataContractResolverStrategy()));
// read it
var heroModel = reader.Query<models.PageSectionHeroContent>(heroContent);
var bodyModel = reader.Query<models.PageSectionBodyContent>(bodyContent);
var footerModel = reader.Query<models.PageSectionFooterContent>(footerContent);
// run query for current page
var queryHero = heroModel.ArrayItems().Where(o => o.DisplayName == keyHero);
var queryBody = bodyModel.ArrayItems().Where(o => o.DisplayName == keyBody);
var queryFooter = footerModel.ArrayItems().Where(o => o.DisplayName == keyFooter);
// models for return
models.PageSectionHeroContent hero;
models.PageSectionBodyContent body;
models.PageSectionFooterContent footer;
// any hero content?
if (queryHero.Any())
hero = new models.PageSectionHeroContent { DisplayName = queryHero.FirstOrDefault().DisplayName,
ContentXML = queryHero.FirstOrDefault().ContentXML };
else
hero = new models.PageSectionHeroContent { DisplayName = "Sorry, there was an error.",
ContentXML = "<details><error>No data was returned.</error></details>" };
// any body content?
if(queryBody.Any())
body = new models.PageSectionBodyContent { DisplayName = queryBody.FirstOrDefault().DisplayName,
ContentXML = queryBody.FirstOrDefault().ContentXML };
else
body = new models.PageSectionBodyContent { DisplayName = "Sorry, there was an error.",
ContentXML = "<details><error>No data was returned.</error></details>" };
// any footer content?
if(queryFooter.Any())
footer = new models.PageSectionFooterContent { DisplayName = queryFooter.FirstOrDefault().DisplayName,
ContentXML = queryFooter.FirstOrDefault().ContentXML };
else
footer = new models.PageSectionFooterContent { DisplayName = "Sorry, there was an error.",
ContentXML = "<details><error>No data was returned.</error></details>" };
// build generic page model
var model = new models.GenericPageModel { PageSectionHeroContent = hero, PageSectionBodyContent = body, PageSectionFooterContent = footer };
return model;
}
catch (Exception ex)
{
//todo: handle, log exception
return null;
}
}
不能确定是什么没有在BaseController
中按时初始化,但找到了解决方案。
免责声明:我和boynamedjib
在同一个开发团队,这个解决方案可能最适合我们的特定情况。话虽如此,我们觉得这个解决方案值得发布,因为它可能会帮助其他遇到这种怪癖的人。
解决方案
解决方案是在使用C#4.0特有的dynamic
类型和ExpandoObjects
以及IDictionary
类型的组合中找到的。
public models.GenericPageDataModel GetGenericPageContent(string keyHero, string keyBody, string keyFooter)
{
try
{
var pageData = new List<models.GenericPageData>
{
new models.GenericPageData{Key = "HeroModel",Value = GetJson("pro_Page_Section_Hero_Content")},
new models.GenericPageData{Key = "BodyModel",Value = GetJson("pro_Page_Section_Body_Content")},
new models.GenericPageData{Key = "FooterModel",Value = GetJson("pro_Page_Section_Footer_Content")}
};
var reader = new JsonReader();
var model = new models.GenericPageDataModel();
foreach (var p in pageData)
{
var objList = new List<ExpandoObject>();
dynamic output = reader.Read(p.Value);
foreach (var h in output)
{
dynamic obj = new ExpandoObject();
foreach (dynamic o in h)
{
var item = obj as IDictionary<String, object>;
item[o.Key] = o.Value;
}
objList.Add(obj);
}
switch (p.Key)
{
case ("HeroModel"):
model.HeroModel = objList.FirstOrDefault(o => o.FirstOrDefault(i => i.Key.Equals("DisplayName")).Value.Equals(keyHero));
break;
case ("BodyModel"):
model.BodyModel = objList.FirstOrDefault(o => o.FirstOrDefault(i => i.Key.Equals("DisplayName")).Value.Equals(keyBody));;
break;
case ("FooterModel"):
model.FooterModel = objList.FirstOrDefault(o => o.FirstOrDefault(i => i.Key.Equals("DisplayName")).Value.Equals(keyFooter));;
break;
default:
break;
}
}
return model;
}
catch (Exception ex)
{
return null;
}
}
支持模型
public class GenericPageData
{
public string Key { get; set; }
public string Value { get; set; }
}
public class GenericPageDataModel
{
public ExpandoObject HeroModel { get; set; }
public ExpandoObject BodyModel { get; set; }
public ExpandoObject FooterModel { get; set; }
}
剃刀的使用
@model my.project.com.Models.ContentModels.GenericPageDataModel
@{
ViewBag.Title = "My Title";
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.heroDisplayName = @Model.HeroModel.ToDictionary(p => p.Key).FirstOrDefault(k => k.Key.Equals("DisplayName")).Value.Value;
}
<h1> @ViewBag.heroDisplayName</h1>