Orchard CMS ContentManager.New<>()指定的Cast无效

时间:2013-10-26 22:26:08

标签: asp.net-mvc orchardcms

我正处于开发新模块的早期阶段。

其中大部分是根据模型等进行布局的。还有所有设置的迁移,我的数据库现在有我的模块的表。

我在致电ContentManager.New<myPart>时遇到以下错误,并希望得到一些帮助。

错误是这样的:

An unhandled exception has occurred and the request was terminated. Please refresh the page. If the error persists, go back
Specified cast is not valid.
System.InvalidCastException: Specified cast is not valid. 
at Orchard.ContentManagement.ContentCreateExtensions.New[T]
              (IContentManager manager, String contentType) 

触发异常的代码块是:

public static T New<T>(this IContentManager manager, string contentType) where T : class, IContent {
            var contentItem = manager.New(contentType);
            if (contentItem == null)
                return null;

            var part = contentItem.Get<T>();
            if (part == null)
                throw new InvalidCastException();

            return part;
        }

以下是我的模块中与我正在努力的操作相关的各个部分:

ContentPart

public class GoogleMapsSettingsPart : ContentPart<GoogleMapsSettingsPartRecord>
{
    public string ApiKey { 
        get { return Record.ApiKey; }
        set { Record.ApiKey = value; }
    }
}

ContentPartRecord

public class GoogleMapsSettingsPartRecord : ContentPartRecord
{
    public virtual string ApiKey { get; set; }
}

处理程序

public GoogleMapsSettingsPartHandler(IRepository<GoogleMapsSettingsPartRecord> repository)
        {
            Filters.Add(StorageFilter.For(repository));
        }

此表的迁移

// Settings Table
SchemaBuilder.CreateTable("GoogleMapsSettingsPartRecord", table => table
       .ContentPartRecord()
       .Column("ApiKey", DbType.String, c => c.WithLength(60))
);

此模型的控制器中的一些代码等

public AdminController(IContentManager contentManager, IShapeFactory shapeFactory, IServiceLocatorService serviceLocatorService, INotifier notifier)
        {
            _contentManager = contentManager;
            _serviceLocatorService = serviceLocatorService;
            _notifier = notifier;
            Shape = shapeFactory;
            T = NullLocalizer.Instance;
        }


        /// <summary>
        /// Display Settings
        /// </summary>
        /// <returns></returns>
        public ActionResult Settings()
        {
            var settings = _serviceLocatorService.GoogleMapsSettings;
            var editor = CreateSettingsEditor(settings);
            var model = _services.ContentManager.BuildEditor(settings);

            return View((object)model);
        }

最后 - 我的电话会抛出此异常的服务

private GoogleMapsSettingsPart _settings;
        public GoogleMapsSettingsPart GoogleMapsSettings
        {
            get {
                if (_settings == null)
                {
                    _settings = _contentManager.Query<GoogleMapsSettingsPart, GoogleMapsSettingsPartRecord>().List().FirstOrDefault();

                    if (_settings == null)
                    {
                        _settings = _contentManager.New<GoogleMapsSettingsPart>("GoogleMapsSettings");
                    }
                }
                return _settings;
            }
        }

发生异常的实际行是_settings = _contentManager.New<GoogleMapsSettingsPart>("GoogleMapsSettings");

我尝试过各种各样的东西代替“GoogleMapsSettings”,但没有任何工作。

我很确定在这一点上它很简单,虽然这样可以避开我......我对Orchard的知识有限,难以理解我

任何帮助将不胜感激:)

3 个答案:

答案 0 :(得分:2)

抛出异常是因为您的内容类型没有指定要获取的部分。

 _contentManager.New<GoogleMapsSettingsPart>("GoogleMapsSettings");

此方法调用会创建类型为GoogleMapSettings的新内容项,并将内容项设为GoogleMapsSettingsPart。但是,GoogleMapSettings内容类型似乎没有GoogleMapsSettingsPart。这就是异常被抛到这里的原因。

var part = contentItem.Get<T>();
if (part == null)
    throw new InvalidCastException();

您必须将部件动态附加到您的内容类型,或者在迁移中执行(或者在管理员中手动添加,但这不是一个好主意)。您的迁移应该如下所示。

this.ContentDefinitionManager.AlterTypeDefinition("GoogleMapsSettings",
    alt => alt
        .WithPart("GoogleMapsSettingsPart");

答案 1 :(得分:0)

好的,所以我修好了......

我对Orchard如何运作的理解仍处于学习阶段。

对于这个特定的操作,我不想在管理员中有一个内容类型 - 虽然不确定为什么在添加ContentType后它仍然无效......

无论如何,将下面的行添加到我的处理程序中可以完成剩下的工作。我相信它实际上是在创建一个临时类型,因此系统中不需要它。

public GoogleMapsSettingsPartHandler(IRepository<GoogleMapsSettingsPartRecord> repository)
        {
            Filters.Add(new ActivatingFilter<GoogleMapsSettingsPart>("GoogleMapsSettings"));
            Filters.Add(StorageFilter.For(repository));

            Filters.Add(new TemplateFilterForRecord<GoogleMapsSettingsPartRecord>("GoogleMapsSettings", "Parts/GoogleMapsSettings"));
        }

答案 2 :(得分:0)

我得到了同样的错误,但在我的情况下,迁移类的一切都很好。 原因是不幸的合并,它删除了我的驱动程序类。 只需看看这个ContentPartDriverCoordinator类的Activating方法代码。在我的情况下,我的内容部分没有partInfo,结果部分变成了ContentPart,因此强制抛出异常

var partInfos = _drivers.SelectMany(cpp => cpp.GetPartInfo()).ToList();

foreach (var typePartDefinition in contentTypeDefinition.Parts) {
    var partName = typePartDefinition.PartDefinition.Name;
    var partInfo = partInfos.FirstOrDefault(pi => pi.PartName == partName);
    var part = partInfo != null 
        ? partInfo.Factory(typePartDefinition) 
        : new ContentPart { TypePartDefinition = typePartDefinition };
    context.Builder.Weld(part);
}