Simplest wat to integrate Unity with MVC3 - asp.net-mvc-3

I have a console app with config:
<?xml version="1.0" encoding="utf-8" ?> <configuration>
<configSections>
<section name="unity" type=
"Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<assembly name="UnityDi.Contracts" />
<assembly name="UnityDi.Domain" />
<assembly name="UnityDi.Services" />
<assembly name="UnityDi.Repositories" />
<namespace name="UnityDi.Contracts" />
<namespace name="UnityDi.Domain" />
<namespace name="UnityDi.Services" />
<namespace name="UnityDi.Repositories" />
<container>
<register type="IUser" mapTo="User"></register>
<register type="IUserService" mapTo="UserService"></register>
<register type="IUserRepository" mapTo="UserRepository"></register>
</container>
</unity>
</configuration>
and Program.cs
namespace UnityDi.Console
{
using System;
using Contracts;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
public static class Program
{
private static readonly IUnityContainer Container =
new UnityContainer().LoadConfiguration();
public static void Main()
{
var dummyUserOne = GetUserReference();
dummyUserOne.UserId = 1;
dummyUserOne.FullName = "Bilbo Baggins";
var dummyUserTwo = GetUserReference();
dummyUserTwo.UserId = 2;
dummyUserTwo.FullName = "Frodo Baggins";
var userService = GetUserServiceReference();
userService.Add(dummyUserOne);
userService.Add(dummyUserTwo);
var users = userService.GetAllUsers();
foreach (var user in users)
{
Console.WriteLine(user.FullName);
}
Console.ReadLine();
}
private static IUser GetUserReference()
{
return Container.Resolve<IUser>();
}
private static IUserService GetUserServiceReference()
{
return Container.Resolve<IUserService>();
}
}
}
That works really well.
I've been doing a lot of searching around and find that solutions published integrating Unity with MVC3 seem to be very verbose in their approach.
Within the context of the code above (and with a requirement to wire up Entity Framework code first), what's the SIMPLEST way for me to integrate Unity with MVC3 and work with my data like above?
I want to use the exact same approach to creating my objects in MVC as above.
Thanks!
Richard
P.s. The closest I found was Unity.Mvc but I can't get it to work like above. I'm probably being stupid though. This is new to me.
EDIT: Working with the proposed answer.
In Web.config for the MVC app (with Unity.Mvc package added)
[snip]
<container>
<register type="IUser" mapTo="User"></register>
<register type="IUserService" mapTo="UserService"></register>
<register type="IUserRepository" mapTo="UserRepository">
<lifetime type="HierarchicalLifetimeManager" />
</register>
</container>
Then in Bootstrapper.cs
namespace Unity.Mvc.Resources
{
using System.Web.Mvc;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using Unity.Mvc3;
public static class Bootstrapper
{
public static void Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer().LoadConfiguration();
container.RegisterControllers();
return container;
}
}
}
Then in the controller (bit of an a-ha moment when I realised the Interface can be any Unity knows about, including it's own):
private readonly IUnityContainer container;
public HomeController(IUnityContainer container)
{
this.container = container;
}
public ActionResult Index()
{
var dummyUserOne = GetUserReference();
dummyUserOne.UserId = 1;
dummyUserOne.FullName = "Bilbo Baggins";
var dummyUserTwo = GetUserReference();
dummyUserTwo.UserId = 2;
dummyUserTwo.FullName = "Frodo Baggins";
var userService = GetUserServiceReference();
userService.Add(dummyUserOne);
userService.Add(dummyUserTwo);
var users = userService.GetAllUsers();
return View(users);
}
private IUser GetUserReference()
{
return container.Resolve<IUser>();
}
private IUserService GetUserServiceReference()
{
return container.Resolve<IUserService>();
}
And again, it works :)
That just leaves the Entity Framework aspect. Need to get DbContext wired up to work with my Domain objects without introducing additional dependencies... Any pointers? Really, very much appreciated.

Install the Unity.Mvc3 nuget package.
go to the bootstrapper code and add your mapping (get it working like that then fiddle around with doing it in a config file if you so desire)
The bootstrapper will 'hook' into mvc to let it know for controller resolution to use unity.
ex:
container.RegisterType<ICustomerRepository, CustomerRepository>();
Any constructors for controllers will look for any interfaces unity needs to do mappings on. If it has to inject IService, it will (As long as it knows about it).
If it has to repeat this process throughout the object grab (IService required IRepository, etc on down the graph) as long as unity knows about it, it will wire everything up.
For the additional question on the Entity Framework, I use an IContext class. In here I define IDbSet Customers. This is similar to this implementation:
http://leomburke.wordpress.com/category/entity-framework/

Related

How to use Session in Models in MVC .NET Core 2.2

I want to use Session in a MVC .NET Core 2.2 project but not only in the Controller but also in the Model.
There are examples to show the usage in Controllers but I did not find any information on how to access the Session in Model classes. Also I need to say that Models are not in the Web project but in a seperate Class Library project.
Is there a proper answer or solution for this problem?
It's generally inadvisable to use the session in a class library.You'd better pass the particular values to your library call or just pass the whole IHttpContextAccessor to get HttpContext in model class.
So instead of accessing the settings in the library method, you do:
1.Class Library.
1) Install below packages for your Class Library:
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
</ItemGroup>
2) Model:
using Microsoft.AspNetCore.Http;
using System;
namespace ClassLibrary1
{
public class Product
{
private readonly IHttpContextAccessor _contextAccessor;
public Product(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
Name = _contextAccessor.HttpContext.Session.GetString("your session key");
}
public string Name { get; set; }
}
}
2.Web App.
1) Startup.cs
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
2) Controller:
public class HomeController : Controller
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HomeController(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
var product = new ClassLibrary1.Product(_httpContextAccessor );
}
}

PrismDryIoc.Forms AutowireViewModel not working

I created a Prism Unity App (from the prism extension pack - really nice), added 2 new views and set up basic navigation between the views. This all worked fine without any hiccups.
What I really want is to use DryIoc (company policy). So I proceeded to remove the unity packages (Unity and Prism.Unity.Forms) and installed the DryIoc Packages (DryIoc and Prism.DryIoc.Forms). Fixed the App.xaml to use the correct namespace (xmlns:prism="clr-namespace:Prism.DryIoc;assembly=Prism.DryIoc.Forms") and alos fixed all the other references to use DryIoc and not the Unity References.
This all compiles and runs without any exceptions. But when I debug it is clear that the AutoWireup does not work as expected (at least as I expect it to). The breakpoint in the ViewModel's constructor (or any other place) is not hit and the Title bindings does not pull through.
Is there a Configuration/Setup or reference that I am missing?
My Code:
App.xaml:
<?xml version="1.0" encoding="utf-8" ?><prism:PrismApplication xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.DryIoc;assembly=Prism.DryIoc.Forms"
x:Class="XamFormsPrism.App"></prism:PrismApplication>
App.xaml.cs:
public partial class App : Prism.DryIoc.PrismApplication
{
public App(IPlatformInitializer initializer = null) : base(initializer) { }
protected override void ConfigureContainer()
{
base.ConfigureContainer();
}
protected override void OnInitialized()
{
this.InitializeComponent();
this.NavigationService.NavigateAsync(NavigationLinks.MainPage);
}
protected override void RegisterTypes()
{
this.Container.RegisterTypeForNavigation<MainPage>();
this.Container.RegisterTypeForNavigation<ViewA>();
this.Container.RegisterTypeForNavigation<ViewB>();
}
}
MainPage.xaml:
<?xml version="1.0" encoding="utf-8" ?><ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="XamFormsPrism.Views.MainPage"
Title="MainPage"><StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label Text="{Binding Title}" />
<Button Text="{Binding NavigateText}" Command="{Binding NavigateCommand}" /> </StackLayout></ContentPage>
MainPageViewModel.cs:
public class MainPageViewModel : BindableBase, INavigationAware
{
private INavigationService navigationService = null;
private string _title = "Jose Cuervo";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
public DelegateCommand NavigateCommand { get; private set; }
public MainPageViewModel(INavigationService navigationService)
{
this.navigationService = navigationService;
this.NavigateCommand = new DelegateCommand(this.navigate, this.canNavigate);
}
private void navigate()
{
this.navigationService.NavigateAsync("ViewA");
}
private bool canNavigate()
{
return true;
}
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
public void OnNavigatedTo(NavigationParameters parameters)
{
if (parameters.ContainsKey("title"))
Title = (string)parameters["title"] + " and Prism";
}
}
As seen above I use the standard naming convention of PageName & PageNameViewModel with the AutoWireUp set to True.
This all worked fine with Unity but I am missing something in DryIoc...but what escapes me.
I have searched the entire project, there is no reference or trace left of Unity.
Any help is much appreciated.
I finally had time again to have a look at this. If I explicit register the ViewModels in the container everything works fine. So I am guessing that there is either a rule missing for the DryIoC container or when using DryIoC you have to explicitly register the ViewModels.

RoleProvider dosn't work with custom IIdentity and IPrincipal on server

I'm using a custom IIdentity and IPrincipal in my ASP.NET MVC application via EF 4.3 as expalined here (and follow accepted answer's solution). Also, I have a custom RoleProvider. In local (using IIS Express), it works currectly. But now, when I upload the application on a real host, it seems all users are in "admin" role! e.g. I create a user that is not in role "admin", but it can access to all protected pages (that need "admin" role). e.g. Role.IsUserInRole always returns true. Have you any idea please? Can you help me? Is there any setting that I should to do in IIS?
I explain that solution and it works for me. I don't now, may be you should rollback to the AuthenticateRequest event.If you want to try this way, you have to remove RoleManagerModule completely from your project. Try this and let me know if works or nop:
// in your module:
public void Init(HttpApplication context) {
_application = context;
// rollback this line:
_application.AuthenticateRequest += ApplicationAuthenticateRequest;
}
// and in web.config
<!-- in system.web section: -->
</system.web>
<!-- other stufs -->
<httpModules>
<remove name="RoleManager"/>
</httpModules>
</system.web>
<!-- and in system.webServer section: -->
<system.webServer>
<!-- other stufs -->
<modules runAllManagedModulesForAllRequests="true">
<remove name="RoleManager"/>
</modules>
<system.webServer>
If you want to keep using the default RoleManager, it gets difficult. I tried creating my own RoleManager by deriving from the default, without any luck.
After 2 days trying several things, I ended up creating some extension methods for RolePrincipal:
public static bool IsEmployee(this RolePrincipal principal)
{
if (IsAuthenticated())
return principal.IsInRole("Employee");
return false;
}
public static bool IsAdmin(this RolePrincipal principal)
{
if (IsAuthenticated())
return principal.IsInRole("Admin");
return false;
}
Created a new WebViewPage class:
public abstract class BaseViewPage : WebViewPage
{
public virtual new RolePrincipal User
{
get
{
if (base.User == null)
return null;
return (RolePrincipal)base.User; //Hard casting: If it goes wrong, it better goes wrong here
}
}
}
public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
public virtual new RolePrincipal User
{
get
{
if (base.User == null)
return null;
return (RolePrincipal)base.User; //Hard casting: If it goes wrong, it better goes wrong here
}
}
}
Modified the web.config in the views folder:
<pages pageBaseType="MyCompany.MyProject.BaseViewPage">
And all my Controllers derive from my BaseController:
public abstract class BaseController : Controller
{
protected virtual new RolePrincipal User
{
get { return HttpContext.User as RolePrincipal; }
}
}
Downside is that the methods query my database everytime they get called.
I'm using MVC 4 btw
Hope this helps anyone

How do I inject into some generic asp.net http handler using Ninject?

I'm a newbie using Ninject and I can't figure out how to inject into my generic http handler. I have a MVC3 project and I'm injecting my services into controllers with no problem at all.
This is what I got in my Ninject App_start class for registering services:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<NLSubscriber.Core.Service.Repository.INLUserRepository>().To<NLSubscriber.Core.Service.Repository.EFDAL.EFNLUserRepository>().InRequestScope();
kernel.Bind<Neticon.Mvc.Helpers.IConfigHelper>().To<Neticon.Mvc.Helpers.AzureEnabledConfigHelper>().InSingletonScope();
kernel.Bind<Neticon.Security.Service.IAuthenticationService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateAuthenticationService()).InRequestScope();
kernel.Bind<Neticon.Security.Service.IMembershipService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateMembershipService()).InRequestScope();
kernel.Bind<Neticon.Security.Service.IRoleManagerService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateRoleManagerService()).InRequestScope();
When I try to get some service from my generic handler by using property injection (with [inject] attribute) I always get null. This is how my handler looks like:
public class SubscriberHandler : IHttpHandler
{
[Inject]
public INLUserRepository userRep { get; set;}
public void ProcessRequest(HttpContext context)
{
var users = userRep.GetUsers(); //userRep is always null here
}
public bool IsReusable
{
get
{
return false;
}
}
}
I have also tried doing it like this:
readonly INLUserRepository userRep;
public SubscriberHandler()
{
using (IKernel kernel = new StandardKernel(new App_Start.NJRepositoryModule()))
{
userRep = kernel.Get<INLUserRepository>();
}
}
but I'm getting an exception: "Error loading Ninject component ICache. No such component has been registered in the kernel's component container.
Suggestions:
1) If you have created a custom subclass for KernelBase, ensure that you have properly
implemented the AddComponents() method.
2) Ensure that you have not removed the component from the container via a call to RemoveAll().
3) Ensure you have not accidentally created more than one kernel."
That's suggesting me that I'm not supposed to instantiate more than one kernel in my application, right?
What am I doing wrong?
Thanks
You could use the dependency resolver:
public class SubscriberHandler : IHttpHandler
{
public INLUserRepository userRep { get; private set; }
public SubscriberHandler()
{
userRep = DependencyResolver.Current.GetService<INLUserRepository>();
}
public void ProcessRequest(HttpContext context)
{
var users = userRep.GetUsers(); //userRep is always null here
}
public bool IsReusable
{
get
{
return false;
}
}
}
I am expecting to get negative feedback from this answer because the service locator pattern is considered by many as an anti-pattern.
But I am not sure whether NInject allows you to use constructor injection for HTTP handlers because they are instantiated by the ASP.NET runtime.
The composition root for IHttpHandlers is the IHttpHandlerFactory. You can create a custom IHttpHandlerFactory that uses Ninject to create an instance of your IHttpHandler. That way you can use constructor injection.
I see you have a "RegisterServices" method in your snippet which suggests you're already using Ninject.Web.Common. What you might not know about NinjectWebCommon.cs is it uses a Bootstrapper class which contains a singleton instance of the Ninject kernel.
As Remo mentioned above, IHttpHandlerFactory is the composition root for IHttpHandler instances and as such you will need to create an implementation of this interface and add the necessary configuration elements to your web.config.
MyHandlerFactory.cs:
public class MyHandlerFactory : IHttpHandlerFactory
{
public bool IsReusable => false;
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
// the bootstrapper class uses the singleton pattern to share the Ninject Kernel across your web app's ApplicationDomain
var kernel = new Bootstrapper().Kernel;
// assuming you have only one IHttpHandler binding in your NinjectWebCommon.cs
return kernel.Get<IHttpHandler>();
}
public void ReleaseHandler(IHttpHandler handler)
{
// nothing to release
}
}
Now, add the necessary config elements for your new handler factory...
Web.config:
<system.web>
<httpHandlers>
<add verb="GET" path="*.customThingImade" type="MyNamespace.MyHandlerFactory, MyAssemblyWhereIPutMyHandlerFactory, Version=1.0.0.0, Culture=neutral" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers>
<add name="MyHandlerFactory" verb="GET" path="*.customThingImade" type="MyNamespace.MyHandlerFactory, MyAssemblyWhereIPutMyHandlerFactory, Version=1.0.0.0, Culture=neutral" preCondition="integratedMode" />
</handlers>
</system.webServer>
Finally, add a binding for your IHttpHandler implementation...
NinjectWebCommon.cs:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<NLSubscriber.Core.Service.Repository.INLUserRepository>().To<NLSubscriber.Core.Service.Repository.EFDAL.EFNLUserRepository>().InRequestScope();
kernel.Bind<Neticon.Mvc.Helpers.IConfigHelper>().To<Neticon.Mvc.Helpers.AzureEnabledConfigHelper>().InSingletonScope();
kernel.Bind<Neticon.Security.Service.IAuthenticationService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateAuthenticationService()).InRequestScope();
kernel.Bind<Neticon.Security.Service.IMembershipService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateMembershipService()).InRequestScope();
kernel.Bind<Neticon.Security.Service.IRoleManagerService>().ToMethod(m => Neticon.Security.Service.SecurityServiceFactory.CreateRoleManagerService()).InRequestScope();
// the binding for your handler factory
Bind<IHttpHandler>().To<SubscriberHandler>();
}

Need help converting PRISM Unity Module Init to PRISM MEF Module Init

I need help converting the following class for use in a program that I am developing. The original was a demo program from IdeaBlade called "PRISM EXPLORER" based on Unity. I need help converting one part from UNITY to MEF. I handled everything else. Just stuck on this one. I already marked my classes with the MEF "[EXPORT(typeof(XXX))]" and I think I need to use the "ComposeExportedValue" somehow. The confusing part is finding the equivelant for this line:
var provider =
(IEntityManagerProvider) _container.Resolve<IPersistenceGateway>();
_container.RegisterInstance<IEntityManagerProvider>(provider);
THANKS!
The following is the entire class I need to convert. You can find the original here: Ideablade PRISM Page
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.Regions;
using Microsoft.Practices.Unity;
using PrismExplorer.Infrastructure;
namespace ModelExplorer.Explorer {
public class ExplorerModule : IModule {
private readonly IUnityContainer _container;
public ExplorerModule(IUnityContainer container) {
_container = container;
}
public void Initialize() {
InitializeContainer();
SetViews();
}
// ToDo: Consider getting from configuration
private void InitializeContainer() {
RegisterGatewayAndEntityManagerProvider();
_container.RegisterType<IQueryRepository, QueryRepository>(
new ContainerControlledLifetimeManager()); // singleton
}
private void RegisterGatewayAndEntityManagerProvider() {
_container.RegisterType<IPersistenceGateway, PrismExplorerPersistenceGateway>(
new ContainerControlledLifetimeManager()); // singleton
var provider =
(IEntityManagerProvider) _container.Resolve<IPersistenceGateway>();
_container.RegisterInstance<IEntityManagerProvider>(provider);
}
private void SetViews() {
var regionManager = _container.Resolve<IRegionManager>();
var view = _container.Resolve<ExplorerView>();
regionManager.AddToRegion(RegionNames.MainRegion, view);
regionManager.RegisterViewWithRegion(RegionNames.MainRegion, typeof(ExplorerView));
}
// Destructor strictly to demonstrate when module is GC'd
//~MevModule() {
// System.Console.WriteLine("Goodbye, MevModule");
//}
}
}
The two corresponding methods on a CompositionContainer are ComposeExportedValue<T>(...), which allows you to add a specific instance to the container, and GetExportedValue<T>(...) which gets an instance of T from the container.
If you can design your types in a way to reduce this use of service location and try and prefer constructor injection, it will make your code much easier to maintain and test. E.g., could your code be transformed into:
[Export(typeof(IModule))]
public class ExplorerModule : IModule
{
[ImportingConstructor]
public ExplorerModule(IPersistenceGateway gateway)
{
}
}

Resources