确保CMSModuleLoader在Kentico CMS 8.2中注册
本文关键字:注册 CMS CMSModuleLoader Kentico 确保 | 更新日期: 2023-09-27 18:28:10
Kentico CMS 8.2的web应用程序项目中有自定义的CMSModuleLoader代码我在Old_App_code''CMS文件夹中添加了这段代码,该文件夹在Global.asax文件中添加了一个函数,代码为
private static void EnsureDynamicModules(object sender, EventArgs e)
{
ModuleEntryManager.EnsureModule<CMSModuleLoader>();
var discovery = new ModuleDiscovery();
var assembly = typeof(CMSModuleLoader).Assembly;
foreach (var module in discovery.GetModules(assembly))
{
ModuleEntryManager.EnsureModule(module);
}
}
此代码正在抛出错误消息:
类型"CMSModuleLoader"不能用作泛型类型或方法"CMS.Core.ModuleEntryManager.EnsureModule()"中的类型参数"T"。没有从"CMSMmodule Loader"到"CMS.Core.ModuleEntry"的隐式引用转换
代码列在下方
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Threading;
using System.Web;
using Aon.Exchange.Core;
using Aon.Exchange.Core.Exceptions;
using Aon.Exchange.Facade.Interfaces;
using Aon.Exchange.Domain.Entities;
using Aon.Exchange.Web.DependencyResolution;
using Common.Logging;
using System.Diagnostics;
using Aon.Exchange.Core.Extensions;
using Aon.Exchange.Core.Common.Logging;
using System.Collections.Specialized;
using CMS.OutputFilter;
using CMS.Membership;
using CMS.Base;
using CMS.Helpers;
/// <summary>
/// Module loader class, ensures initialization of other modules through this partial class
/// </summary>
public partial class CMSModuleLoader : CMSModuleLoaderBase
{
/// <summary>
/// Constructor
/// </summary>
public CMSModuleLoader()
: base("CMSModuleLoader")
{
}
private class CustomSecurityEventsAttribute : CMS.Base.CMSLoaderAttribute
{
/// <summary>
/// Called automatically when the application starts
/// </summary>
public override void Init()
{
SecurityEvents.Authenticate.Execute += new EventHandler<AuthenticationEventArgs>(Authenticate_Execute);
}
/// <summary>
/// called on every kentico authenticate attempt
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Authenticate_Execute(object sender, AuthenticationEventArgs args)
{
if (args.User != null) //the authenticate was successful
{
try
{
var accountFacade = WebContainer.Instance.Container.GetInstance<IAccountFacade>();
accountFacade.ReconcileOnLogin(args.UserName);
}
catch (Exception e)
{
var logger = LogManager.GetCurrentClassLogger();
var ex = new Exception("IAccountFacade.ReconcileOnLogin method throw an error communicating with dynamics, the issue is not resolvable from Kentico thus regardless of the permission level of the current user, the exception will be bubbled up and the user will be shown error details or the custom error page.", e);
logger.Fatal(x => x("The current exception is caused by dynamics/data problems and the user will not be allowed to login. A system admin with access to dynamics is required to resolve the problem.", e));
throw ex;
}
ResetPasswordAttempts(args.User);
}
}
/// <summary>
/// Resets the number of password attempts for a user. We have to pass the userinfo object thru the layers because
/// doing a get, update, change from to the same userinfo object that we have here DOES NOT WORK. Luckily we can avoid giving all the layers
/// reference to the kentico dlls by passing the userinfo as an object and unpacking it in the repository.
/// </summary>
private void ResetPasswordAttempts(UserInfo user)
{
try
{
var accountFacade = WebContainer.Instance.Container.GetInstance<IAccountFacade>();
accountFacade.ResetPasswordAttempts(user);
}
catch (KenticoConfigurationException e)
{
var logger = LogManager.GetCurrentClassLogger();
logger.Warn(x => x("An exception was thrown during the IAccountFacade.ResetPasswordAttempts method.", e));
if (user.IsGlobalAdministrator)
{
logger.Error(x => x("IAccountFacade.ResetPasswordAttempts method throw an error, however because the user is logged in as a Kentico Global Admin, the system will ignore the error because the cause might be Kentico configuration and the Gloabl Admin who is logging in could fix the issue.", e));
}
else
{
var ex = new Exception("IAccountFacade.ResetPasswordAttempts method throw an error and the current user does not have the permissions to fix any potential Kentico configuration problems. The current user will not be allowed into the system.", e);
logger.Fatal(x => x("The current user does not have the permissions to login with the current system configuration errors; requires a user with Global Admin rights in kentico", e));
throw ex;
}
}
}
}
private class CustomErrorEventsAttribute : CMS.Base.CMSLoaderAttribute
{
/// <summary>
/// Called automatically when the application starts
/// </summary>
public override void Init()
{
SystemEvents.Exception.Execute += new EventHandler<SystemEventArgs>(UnhandledException_Execute);
}
private void UnhandledException_Execute(object sender, SystemEventArgs e)
{
try
{
//log exception
var logger = LogManager.GetCurrentClassLogger();
logger.Error(x => x("Unhandled Exception caught by Kentico Global Exception handler", e.Exception));
}
catch
{
//swallow exceptions created when handling an exception.
}
var routeToCustomErrorPage = bool.Parse(ConfigurationManager.AppSettings[AppSettingKeys.FriendlyErrorRedirect_Enabled]);
var request = HttpContext.Current.Request;
var response = HttpContext.Current.Response;
//if web.config setting says so, and this isn't an api request, route to friendly error page
if (routeToCustomErrorPage && !request.Url.AbsolutePath.Contains("/api/"))
{
response.Redirect("~/CMSTemplates/AonExchange/FriendlyErrorPage.htm");
}
}
}
private class CustomSessionEventsAttribute : CMS.Base.CMSLoaderAttribute
{
/// <summary>
/// Called automatically when the application starts
/// </summary>
public override void Init()
{
//CMSSessionEvents.Start.Before += new EventHandler<EventArgs>(OnBeginSession); -- Kentico 7
SessionEvents.UpdateSession.Before += new EventHandler<CMSEventArgs>(OnBeginSession);
}
private void OnBeginSession(object sender, EventArgs e)
{
var userSessionFacade = WebContainer.Instance.Container.GetInstance<IUserSessionFacade>();
if (userSessionFacade.IsAuthenticated())
{
var log = LogManager.GetCurrentClassLogger();
try
{
log.Info(x => x("Http request was authenticated, but a new session was created. Logging the user out and responding with an http redirect response."));
var accountFacade = WebContainer.Instance.Container.GetInstance<IAccountFacade>();
// This call to redirect will function with both normal page requests and ajax because of the SuppressFormsAuthenticationRedirectModule
accountFacade.Logout();
}
catch (Exception ex)
{
log.Error(x => x("An exception occurred while logging the user out because of a new session", ex));
}
}
}
}
private class CustomRequestEventsAttribute : CMS.Base.CMSLoaderAttribute
{
/// <summary>
/// Called automatically when the application starts
/// </summary>
public override void Init()
{
//CMSRequestEvents.Begin.Before += new EventHandler<EventArgs>(OnBeforeBeginRequest); -- Kentico 7
//CMSRequestEvents.Begin.After += new EventHandler<EventArgs>(OnBeginRequest); -- Kentico 7
//CMSRequestEvents.End.Before += new EventHandler<EventArgs>(OnEndRequest); -- Kentico 7
RequestEvents.Prepare.Execute += new EventHandler<EventArgs>(OnBeforeBeginRequest);
RequestEvents.Begin.Execute += new EventHandler<EventArgs>(OnBeginRequest);
RequestEvents.End.Execute += new EventHandler<EventArgs>(OnEndRequest);
}
private void OnBeforeBeginRequest(object sender, EventArgs e)
{
if ((HttpContext.Current != null) && (HttpContext.Current.Request != null))
{
// Loads the request headers as a collection.
NameValueCollection headers = HttpContext.Current.Request.Headers;
// Gets the value from the FRONT-END-HTTPS header.
string forwardedSSL = headers.Get("FRONT-END-HTTPS");
CMS.Helpers.RequestContext.IsSSL = false;
// Checks if the original request used HTTPS.
if (!string.IsNullOrEmpty(forwardedSSL) && forwardedSSL.Equals("on", StringComparison.InvariantCultureIgnoreCase))
{
var log = LogManager.GetCurrentClassLogger();
log.Info(x => x("Https offloading is enabled."));
CMS.Helpers.RequestContext.IsSSL = true;
}
}
}
private void OnBeginRequest(object sender, EventArgs e)
{
if (HttpContext.Current != null)
{
HttpContext.Current.Items.Add("RequestId", Guid.NewGuid().ToString());
}
if (bool.Parse(ConfigurationManager.AppSettings[AppSettingKeys.MethodTrace_Enabled]))
{
var stopwatch = WebContainer.Instance.Container.GetInstance<Stopwatch>();
var log = LogManager.GetCurrentClassLogger();
log.Trace(x => x("Starting request for {0}", HttpContext.Current.Request.UrlOriginal().ToString()));
stopwatch.Start();
}
}
private void OnEndRequest(object sender, EventArgs e)
{
if (bool.Parse(ConfigurationManager.AppSettings[AppSettingKeys.MethodTrace_Enabled]))
{
var stopwatch = WebContainer.Instance.Container.GetInstance<Stopwatch>();
var log = LogManager.GetCurrentClassLogger();
stopwatch.Stop();
if (log.IsTraceEnabled)
log.Trace(new MethodTimingMessage(stopwatch.ElapsedMilliseconds, 0, "CMSLoader.OnEndRequest", string.Format("{0} execution time in milliseconds for {1}. ::Total Page Request::", stopwatch.ElapsedMilliseconds, HttpContext.Current.Request.UrlOriginal().ToString())));
}
if (HttpContext.Current != null)
{
HttpContext.Current.Items.Remove("RequestId");
}
}
}
/// <summary>
/// Attribute class that ensures the loading of new relic JavaScript insertion
/// </summary>
private class CustomNewRelicSubstitutionLoader : CMS.Base.CMSLoaderAttribute
{
/// <summary>
/// Called automatically when the application starts
/// </summary>
public override void Init()
{
//OutputFilter.OnResolveSubstitution += ResolveCustomSubstitutions;
}
/// <summary>
/// Called to substitute the ~newrelic~ token from the kentico head element into the new relic code to instrument browser data.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ResolveCustomSubstitutions(object sender, SubstitutionEventArgs e)
{
if (!e.Match)
{
switch (e.Expression.ToLowerInvariant())
{
case "newrelic":
e.Result = NewRelic.Api.Agent.NewRelic.GetBrowserTimingHeader();
e.Match = true;
break;
}
}
}
}
}
您需要用自定义属性CustomSecurityEventsAttribute标记CMSModuleLoader,如下所示:
[CustomSecurityEvents]
public partial class CMSModuleLoader : CMSModuleLoaderBase