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

时间:2012-01-12 19:06:18

标签: c# asp.net-mvc-3 inheritance singleton

背景

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

  1. 从远程服务器获取一些JSON。
  2. 根据传入的密钥(英雄,正文,页脚)运行LINQ查询。
  3. 将通用模型返回到视图。
  4. 此代码在从基本控制器继承的控制器中运行时工作正常,但是当放置在基本控制器中并从继承的控制器调用时,我收到以下错误:

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

1 个答案:

答案 0 :(得分:1)

无法确定在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; }
        }

Razor用法

@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>