I'm using Moq to help in testing my ASP.NET MVC2 application.
Problem: ArgumentException was unhandled by user code. Unable to obtain public key for StrongNameKeyPair
This code has been adapted from Scott Hanselman's NerdDinner1.
HomeController CreateHomeControllerAs(string userName)
{
var mock = new Mock<ControllerContext>();
mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(userName); // fails here
mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);
var controller = new HomeController();
controller.ControllerContext = mock.Object;
return controller;
}
[TestMethod]
public void should_be_able_to_get_to_index_page_logged_in()
{
HomeController controller = CreateHomeControllerAs("dave");
}
Using Moq referenced... VS2010 under WinXP.
There's nothing wrong with your code. I've just tested it and it worked fine. The problem is with the Moq assembly. You need to grant specific permissions to the C:\Documents and Settings\AllUsers\ApplicationData\Microsoft\Crypto\RSA\MachineKeys folder. Checkout this discussion.
Also right click on the Moq.dll in Windows Explorer and in the properties make sure that it is not locked. When you download some DLL from the internet Windows automatically applies restricted permissions to it.
Related
I'm using ASP.Net Identity and in my Web Api project in its AccountController I want to send verification email to new users. I have plugged my email service using MVCMailer to the ASP.Net identity.
public class EmailService : IIdentityMessageService
{
private readonly IUserMailer _userMailer;
public EmailService(IUserMailer userMailer)
{
_userMailer = userMailer;
}
public Task SendAsync(IdentityMessage message)
{
_userMailer.DeliverMessage(message.Body);
// Plug in your email service here to send an email.
return Task.FromResult(0);
}
}
#
public class UserMailer : MailerBase, IUserMailer
{
public UserMailer()
{
MasterName = "_Layout";
}
public virtual IMailMessage DeliverMessage(string message)
{
var mailMessage = new MailMessage();
mailMessage.To.Add("hashemp206#yahoo.com");
mailMessage.Subject = "Welcome";
//ViewData = new System.Web.Mvc.ViewDataDictionary(model);
PopulateBody(mailMessage, "Welcome");
mailMessage.Send();
return mailMessage;
}
my custom ASP.Net Identiy is in a seperate project. and as you see above EmailService is dependent on IUserMailer interface. and IUserMailer implementation is in another project MyProject.MVCMailer (this project is an MVC project)
in my dependency resolver in web api I try to resolve this dependency
container.Bind<IUserMailer>().To<UserMailer>().InSingletonScope();
but MVCMailer has a dependency to System.Web.MVC and ninject complain for this reference to initialize USerMailer.
so the problem is here I dont want to add System.Web.MVC to my Web Api project.
how can I use MVCMailer without referencing to System.Web.MVC in my web api project?
I'm a little confused on what you're trying to do but if I'm understanding you correctly you are trying to call your API and then send out an email. Since you are not passing anything from the API into the email (and even if you were) just call your API and return a response object. Once the MVC project recieves the response send the email from the MVC project. Your API should know about objects in your MVC project unless there is a really good reason. Think of them (your MVC and API projects) as two separate entities all together that don't know about each other.
I have an MVC4 Web API project and I making use of Mark Seemann's Hyprlinkr component to generate Uris to linked resources. (Customer -> Addresses for example).
I have already followed Mark's guide on Dependency injection with Web API (changing appropriately for Ninject) bit I can't quite work out what I should do to inject a IResourceLinker into my controllers.
Following Mark's guide my IHttpControllerActivator.Create create method looks like this:
IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
var controller = (IHttpController) _kernel.GetService(controllerType);
request.RegisterForDispose(new Release(() => _kernel.Release(controller)));
return controller;
}
It is in this method that the Hyprlinkr readme suggests to create the RouteLinker. Unfortunately I'm not sure how to register this with Ninject.
I can't just bind like below, as this results in multiple bindings:
_kernel.Bind<IResourceLinker>()
.ToMethod(context => new RouteLinker(request))
.InRequestScope();
I've got rebind working like this:
_kernel.Rebind<IResourceLinker>()
.ToMethod(context => new RouteLinker(request))
.InRequestScope();
But I'm concerned that changing the ninject binding graph is potentially a bad thing to do on every request.
What is the best way to achieve this?
Update following the request from Paige Cook
I'm using rebind here:
IHttpController IHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
_kernel.Rebind<IResourceLinker>()
.ToMethod(context => new RouteLinker(request))
.InRequestScope();
var controller = (IHttpController) _kernel.GetService(controllerType);
request.RegisterForDispose(new Release(() => _kernel.Release(controller)));
return controller;
}
IHttpControllerActivator.Create is called on every request. The rest of the bindings are made in the standard way, by standard I mean in the class generated by using the Ninject.MVC3 nuget package.
My controller looks like this:
public class CustomerController : ApiController
{
private readonly ICustomerService _customerService;
private readonly IResourceLinker _linker;
public CustomerController(ICustomerService customerService, IResourceLinker linker)
{
_customerService = customerService;
_linker = linker;
}
public CustomerModel GetCustomer(string id)
{
Customer customer = _customerService.GetCustomer(id);
if (customer == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return
new CustomerModel
{
UserName = customer.UserName,
Firstname = customer.Firstname,
DefaultAddress = _linker.GetUri<AddressController>(c => c.Get(customer.DefaultAddressId)),
};
}
}
Register a delegate Function to give you the linker
_kernel.Bind<Func<HttpRequestMessage, IResourceLinker>>()
.ToMethod(context => (request) => new RouteLinker(request));
Inject the delegate
readonly Func<HttpRequestMessage, IResourceLinker> _getResourceLinker;
public controller(Func<HttpRequestMessage, IResourceLinker> getResourceLinker) {
_getResourceLinker = getResourceLinker;
}
Use in your actions
public async Task<Thingy> Get() {
var linker = _getResourceLinker(Request);
linker.GetUri( ... )
}
If you only need to use RouteLinker from ApiController derivates, you don't really need to go through all the DI hoops.
You can just create it within the Controller like this:
var linker = new RouteLinker(this.Request);
IMO, using DI with RouteLinker first becomes valuable when you need a RouteLinker further down the stack - but then again, I also only use RouteLinker as a Concrete Dependency...
Thanks for adding the code sample. Based on what you have posted, you are running into your Bind/Rebind issue because you are issuing the _kernel.Bind<IResourceLinker> in the IHttpControllerActivtor.Create method every time.
You need to move the _kernel.Bind<IResourceLinker> to be registered the same way your are registering the rest of your bindings in the
...standard way, by standard I mean in the class generated by using the Ninject.MVC3 nuget package.
There should not be any need for the IResourceLinker to be binded multiple times, and this is why you are getting multiple instances, because the binding is firing every time a controller is created by the IHttpControllerActivator.
Update:
Sorry that I missed the need for an HttpRequestMessage as a constructor argument, I would go with Anthony Johnson's answer on this one.
I'm testing the Account/Loggon action using the built-in testing tool of Visual Studio 2010 and the class library from this article to create a fake controller context.
When I run the test method, this code line:
FormsAuthentication.SetAuthCookie(username, false);
throws an exception: Object reference not set to an instance of an object
To test the loggon action, I think I should create a controller with a fake controller context that has a cookie collection. Here is my testing code block:
AccountController controller = new AccountController();
var cookies = new HttpCookieCollection();
controller.ControllerContext = new FakeControllerContext(controller, cookies);
ActionResult result = controller.RemoteLogOn(username, password);
I'm not sure if this is the right way, but this is what we do, and it works.
Instead of directly using FormsAuthentication.SetAuthCookie, abstract it into an interface, e.g IFormsAuthenticationService, and implement as per regular.
Accept that in your MVC controllers where required, e.g:
public AccountController(IFormsAuthenticationService formsAuthenticationService)
{
_formsAuthenticationService = formsAuthenticationService; // should use DI here
}
public ActionResult LogOn(string username, string pw)
{
if (yourLogicWhichChecksPw)
_formsAuthenticationService.SetAuthCookie(username, false);
return RedirectToAction("Index");
}
Then in your unit-test, use something like Moq to fake out the interface.
var username = "blah";
var pw = "blah";
var fakesFormsAuth = new Mock<IFormsAuthenticationService>();
fakeFormsAuth.Verify(x => x.SetAuthCookie(username, false), Times.AtLeastOnce());
var controller = new AccountController(fakedFormsAuth.Object);
controller.LogOn(username, pw);
The reason for mocking this is because there is absolutely no need to unit-test Forms Authentication. It's a built-in, well tested and stable part of the ASP.NET framework. That's why we mock things where we don't care about the underlying implementation, instead we only test that certain conditions were met (it was called, exception was thrown, some variable was set, etc).
Test your own code, not the mechanics of .NET.
As for Stephen Walther's article, that's more for faking the RequestContext when certain code your testing expects data in the Request. Such as the User.Identity, Request.IsAuthenticated, Form variables, etc. That's where you need to fake the context, such as the following code:
public ActionResult Save(SomeModel)
{
var user = Request.User.Identity; // this will be null, unless you fake the context.
}
after a lot of googling and reading several solutions on how to manage mixed mode authentication in ASP.NET apps, I still have no fitting solution for my problem.
I've got to implement an intranet application for a bunch of different user groups. Until now i've used windows authenthication which was very simple to implement. My problems arise when it comes to authorizing usergroups for special application functionalities.
Using [Authorize(Users = "DOMAIN\\USER")] works great but due to that i have no access to the active directory managament, it is impossible to me to configure rolemanagement in the way I need it for my application.
What I'd like to do is defining custom roles and memberships in addition to the ones that are defined within the active directory (is such an extension possible? e.g. by implementing an own membershipprovider?).
What do you think is the best solution for my problem. Do I really have to implement a complex mixed mode authentication with forms authentication in addition to windows authentication?
Used Technologies:
MS SQL Server 2008
MS VS 2010
ASP.NET MVC 3 - Razor View Engine
Telerik Extensions for ASP.NET MVC
IIS 7 on Windows Server 2008
EDIT (final solution thanks to the help of dougajmcdonald):
After pointing me to use a custom IPrincipal implementation I've found some solutions here and here. Putting everything together I came to the following solution:
1.Create a custom principal implementation:
public class MyPrincipal: WindowsPrincipal
{
List<string> _roles;
public MyPrincipal(WindowsIdentity identity) : base(identity) {
// fill roles with a sample string just to test if it works
_roles = new List<string>{"someTestRole"};
// TODO: Get roles for the identity out of a custom DB table
}
public override bool IsInRole(string role)
{
if (base.IsInRole(role) || _roles.Contains(role))
{
return true;
}
else
{
return false;
}
}
}
2.Integrate my custom principal implementation into the application through extending the "Global.asax.cs" file:
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
WindowsIdentity wi = (WindowsIdentity)HttpContext.Current.User.Identity;
MyPrincipal mp = new MyPrincipal(wi);
HttpContext.Current.User = mp;
}
}
3.Use my custom roles for authorization in my application
public class HomeController : Controller
{
[Authorize(Roles= "someTestRole")]
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
}
It works!!! yeah!
I'm not sure if this still applies in MVC, but in Webforms one way to do this would be as follows:
Create a new IPrincipal implementation perhaps extending WindowsPrincipal
In this class, give it a collection of roles (your own custom roles)
Populate those roles, by perhaps getting them from the DB.
Override IsInRole to return true if the role provided is EITHER true from the base call (WindowsAuthentication/Role) OR from your own custom role collection.
This way you can still hook into Principal.IsInRole("MyRole") and also the principal [PrincipalPermission()] annotation.
Hope it helps.
EDIT in answer to q's:
To integrate the principal into the authorisation you need to write your own method for OnAuthenticate in the global.asax for the type of authentication, so I would guess for you, something like this:
void WindowsAuthentication_OnAuthenticate(object sender, WindowsAuthenticationEventArgs e)
{
// ensure we have a name and made it through authentication
if (e.Identity != null && e.Identity.IsAuthenticated)
{
//create your principal, pass in the identity so you know what permissions are tied to
MyCustomePrincipal opPrincipal = new MyCustomePrincipal(e.Identity);
//assign your principal to the HttpContext.Current.User, or perhaps Thread.Current
HttpContext.Current.User = opPrincipal;
}
}
I believe Authorize came in at a later date to the PrincipalPermission, but I'm not too sure as to when/why of the differences I'm afraid :( - sorry!
How can i unit test a controller that contains HttpConext using moles framework?
My Code for the controller is
public ActionResult Index()
{
MyRepositoryClass myRepo = new MyRepositoryClass (System.Web.HttpContext.Current);
string fs = ipser.GetCityName();
return View();
}
My code for the controller in unit test project is
public class MyClassTest
{
[TestMethod]
[HostType("Moles")]
public void Index_Test()
{
string originalViewName="Index";
MyController myContl = new MyController ();
var result =myContl.Index() as ViewResult;
Assert.IsNotNull(result, "Should return a view");
Assert.AreEqual(originalViewName, result.ViewName, "View name should have been {0}", originalViewName);
}
How should i test my controller using moles framework?
The quick answer is don't use Moles, but instead remove your dependency on the static HttpContext object.
If you use HttpContextBase (in System.Web.Abstractions in .NET 4.0) instead of HttpContext you'll be able to supply a fake HttpContext in your unit tests. You will need to use an IoC container in your MVC app and ensure you map HttpContextWrapper(HttpContext.Current) to HttpContextBase in when configuring the IoC container.
There's plenty of info on how this is done on the web. Just Google for HttpContextBase, HttpContextWrapper and MVC and I'm sure you'll find plenty of example code and explanations to help you.