MVC3基本控制器崩溃,相同代码在继承的控制器中工作

本文关键字:控制器 继承 代码 工作 崩溃 MVC3 | 更新日期: 2023-09-27 18:20:04

背景

.NET 4、C#、MVC3,使用JsonFx对数据进行序列化和反序列化。基本控制器已扩展为拦截所有请求并执行以下操作:

  1. 从远程服务器获取一些JSON
  2. 基于传入的键(英雄、正文、页脚)运行LINQ查询
  3. 将通用模型返回到视图中

当在继承自基本控制器的控制器中运行时,此代码运行良好,但当放置在基本控制器中并从继承的控制器调用时,我会得到以下错误:

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

MVC3基本控制器崩溃,相同代码在继承的控制器中工作

不能确定是什么没有在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>