У меня проблема с разрешением компонента с Unity в моем приложении .NET MVC 5.
В моей папке App_Start я сгенерировал UnityConfig.cs и UnityMvcActivator.cs, который выглядит следующим образом:
public static class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer Container => container.Value;
#endregion
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below.
// Make sure to add a Unity.Configuration to the using statements.
// container.LoadConfiguration();
container.AddNewExtension<Interception>();
container.RegisterType<ILogger, EntLibFileLogger>(new ContainerControlledLifetimeManager(),
new InjectionConstructor(ConfigurationManager.AppSettings["logTrace"],
int.Parse(ConfigurationManager.AppSettings["logSize"])));
container.RegisterType<IUserRepository, UserRepository>(new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingInterceptionBehavior>());
container.RegisterType<IUserProvider, UserProvider>(new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<LoggingInterceptionBehavior>());
...
}
}
public static class UnityMvcActivator
{
/// <summary>
/// Integrates Unity when the application starts.
/// </summary>
public static void Start()
{
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));
DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
/// <summary>
/// Disposes the Unity container when the application is shut down.
/// </summary>
public static void Shutdown()
{
UnityConfig.Container.Dispose();
}
}
Перехват выглядит так:
class LoggingInterceptionBehavior : IInterceptionBehavior
{
private readonly ILogger _logger;
public LoggingInterceptionBehavior(ILogger logger)
{
_logger = logger;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
var methodDesc = $"{input.MethodBase.DeclaringType.Name}.{input.MethodBase.Name}";
var args = input.Arguments == null || input.Arguments.Count == 0
? "null"
: JsonConvert.SerializeObject(input.Arguments);
// Before invoking the method on the original target.
_logger.Log($"{methodDesc} start. Arguments: {args}", LogLevel.Info);
// Invoke the next behavior in the chain.
var result = getNext()(input, getNext);
// After invoking the method on the original target.
if (result.Exception != null)
{
_logger.Log($"{methodDesc} threw exception. {result.Exception.GetBaseException()}", LogLevel.Error);
}
else
{
_logger.Log($"{methodDesc} end", LogLevel.Info);
}
return result;
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public bool WillExecute
{
get { return true; }
}
}
Я также настроил фильтр авторизации, где следующий код:
public class SayDoAuthorizeAttribute : AuthorizeAttribute
{
private readonly string[] allowedRoles;
public SayDoAuthorizeAttribute() : base()
{
}
public SayDoAuthorizeAttribute(params string[] roles)
{
allowedRoles = roles;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var userRoles = SayDoAuthorizeHelper.GetRolesAndCacheThem(httpContext);
bool authorize = false;
foreach (var role in allowedRoles)
{
if (userRoles.Contains(role))
{
authorize = true;
break;
}
}
return authorize;
}
...
}
Проблема в том, что UnityConfig.Resolve не удается разрешить компонент IUserProvider в следующем методе SayDoAuthorizeHelper.GetRolesAndCacheThem. (Я хочу, чтобы этот класс был статическим, потому что методы IsUserInRole и IsUserInRoles также используются в видах бритвы.
public static class SayDoAuthorizeHelper
{
public static IEnumerable<string> GetRolesAndCacheThem(HttpContextBase httpContext)
{
var nameFromSession = httpContext.Session[Constants.SessionKeyUserPreselectSession];
var userName = (nameFromSession != null) ? (string)nameFromSession : httpContext.User.Identity.Name;
var rolesString = (string)httpContext.Cache.Get(userName);
if (string.IsNullOrEmpty(rolesString))
{
var userProvider = UnityConfig.Container.Resolve<IUserProvider>();
var roles = userProvider.GetUserRolesNames(userName);
rolesString = string.Join(",", roles);
//set absolute cache
var minutesToCacheRoles = double.Parse(ConfigurationManager.AppSettings[Constants.KeyCacheUserRolesInMinutes]);
httpContext.Cache.Insert(userName, rolesString, null, DateTime.Now.AddMinutes(minutesToCacheRoles), Cache.NoSlidingExpiration);
return roles;
}
return rolesString.Split(',').ToList();
}
public static bool IsUserInRole(System.Security.Principal.IPrincipal userPrincipal, string roleName)
{
var userRoles = GetRolesAndCacheThem(new HttpContextWrapper(HttpContext.Current));
return userRoles.Contains(roleName);
}
public static bool IsUserInRoles(System.Security.Principal.IPrincipal userPrincipal, string[] roleNames)
{
var userRoles = GetRolesAndCacheThem(new HttpContextWrapper(HttpContext.Current));
foreach (var roleName in roleNames)
{
if (userRoles.Contains(roleName))
{
return true;
}
}
return false;
}
}
Когда у меня установлена точка останова на линии
var userProvider = UnityConfig.Container.Resolve ();
затем не генерируется исключение, и код все еще продолжается, но я вижу в локальных переменных, что userProvider выдал исключение типа 'System.IO.FileNotFoundException' Abb.Czopc.SayDo.BusinessLogic.Interface.IUserProvider {System.IO.FileNotFoundException}
с сообщением «Не удается загрузить сборку« 15bd37ce9f8a41d9b9916a1ebadc536a ».». Но в окне вывода я вижу, что сборка была загружена.
'iisexpress.exe' (CLR v4.0.30319: / LM / W3SVC / 2 / ROOT-1-131699797337577440): загружен '15bd37ce9f8a41d9b9916a1ebadc536a'.
Когда я регистрируюсь в UnityConfig без перехвата, все работает хорошо.
container.RegisterType<IUserRepository, UserRepository>();
container.RegisterType<IUserProvider, UserProvider>();
Я также пытался заменить InterfaceInterceptor на VirtualMethodInterceptor, но с тем же результатом.
Кто-нибудь может помочь? Я не знаю, что не так. Спасибо за помощь.
Решение написано в VS 2015, список пакетов nuget здесь:
<package id="Abb.Czopc.Common.Log" version="1.0.1" targetFramework="net451" />
<package id="Abb.Czopc.Common.Log.EntLibLogger" version="1.0.1" targetFramework="net451" />
<package id="Antlr" version="3.5.0.2" targetFramework="net451" />
<package id="AutoMapper" version="6.2.2" targetFramework="net451" />
<package id="EnterpriseLibrary.Common" version="6.0.1304.0" targetFramework="net451" />
<package id="EnterpriseLibrary.Logging" version="6.0.1304.0" targetFramework="net451" />
<package id="jQuery" version="3.3.1" targetFramework="net451" />
<package id="jQuery.Validation" version="1.17.0" targetFramework="net451" />
<package id="Microsoft.AspNet.Mvc" version="5.2.4" targetFramework="net451" />
<package id="Microsoft.AspNet.Razor" version="3.2.4" targetFramework="net451" />
<package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net451" />
<package id="Microsoft.AspNet.WebPages" version="3.2.4" targetFramework="net451" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.8" targetFramework="net451" />
<package id="Microsoft.jQuery.Unobtrusive.Ajax" version="3.2.5" targetFramework="net451" />
<package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.9" targetFramework="net451" />
<package id="Microsoft.Net.Compilers" version="2.7.0" targetFramework="net451" developmentDependency="true" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net451" />
<package id="Modernizr" version="2.8.3" targetFramework="net451" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net451" />
<package id="Respond" version="1.4.2" targetFramework="net451" />
<package id="Unity.Abstractions" version="3.3.0" targetFramework="net451" />
<package id="Unity.Container" version="5.8.5" targetFramework="net451" />
<package id="Unity.Interception" version="5.5.1" targetFramework="net451" />
<package id="Unity.Mvc" version="5.0.13" targetFramework="net451" />
<package id="WebActivatorEx" version="2.2.0" targetFramework="net451" />
<package id="WebGrease" version="1.6.0" targetFramework="net451" />