I've just read more than one and I don't find any solution for my problem. I've create WebApi + MVC and Unit Test project with FrameWork 4.5. I have this HomeController.cs with this method:
using Net.Personal.Authentication.FormAuthentication;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
namespace FormAuthenticationProva.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Title = "Home Page";
var guidAccount = "xxxxxxxx-xxxx-xxxx-xxxx-422632e0bd95";
var userData = new CookieUserData(guidAccount) { GuidAccount = guidAccount };
HttpContextBase httpContextBase = this.HttpContext;
AuthenticationProvider _authProvider = new AuthenticationProvider(httpContextBase.ApplicationInstance.Context);
_authProvider.CheckAuthorizationForUrl("http://pippo");
return View();
}
}
}
And the HomeControllerTest.cs with this code:
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FormAuthenticationProva.Controllers;
using Moq;
using System.Web;
using System.Collections.Specialized;
using System.Web.Routing;
namespace FormAuthenticationProva.Tests.Controllers
{
[TestClass]
public class HomeControllerTest
{
[TestMethod]
public void Index()
{ // Disposizione
var formData = new NameValueCollection { { "id", "test" } };
var request = new Mock<HttpRequestBase>();
request.SetupGet(r => r.Form).Returns(formData);
var context = new Mock<HttpContextBase>();
context.SetupGet(c => c.Request).Returns(request.Object);
var controller = new HomeController();
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
// Azione
ViewResult result = controller.Index() as ViewResult;
// Asserzione
Assert.IsNotNull(result);
Assert.AreEqual("Home Page", result.ViewBag.Title);
}
}
}
And the AuthenticationProvider.cs class is here:
/* AuthenticationProvider.cs code */
using System;
using System.Security.Principal;
using System.Threading;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.Security;
namespace Net.Personal.Authentication.FormAuthentication
{
public class AuthenticationProvider : IFormsAuthentication
{
public AuthContextConfiguration AuthContextConfiguration { get; set; }
public AuthenticationProvider() {}
public AuthenticationProvider(HttpContext context , AuthContextConfiguration authContextConfiguration = null)
{
AuthContextConfiguration = AuthContextConfiguration ?? new AuthContextConfiguration(context);
}
private void SetPrincipal(IPrincipal principal)
{
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
}
public void SignIn(string userName, bool createPersistentCookie)
{
FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
}
public void SignIn(string userName, bool createPersistentCookie, ICookieUserData userData)
{
this.SetAuthCookie<ICookieUserData>(userName, true, userData);
HttpContext.Current.Cache.Insert(userName, userData);
}
public int SetAuthCookie<T>( string name, bool rememberMe, T userData)
{
/// In order to pickup the settings from config, we create a default cookie and use its values to create a
/// new one.
if (string.IsNullOrEmpty(((ICookieUserData)userData).Name)) ((ICookieUserData)userData).Name = name;
var cookie = FormsAuthentication.GetAuthCookie(name, rememberMe);
var ticket = FormsAuthentication.Decrypt(cookie.Value);
var newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration,
ticket.IsPersistent, new JavaScriptSerializer().Serialize(userData), ticket.CookiePath);
var encTicket = FormsAuthentication.Encrypt(newTicket);
/// Use existing cookie. Could create new one but would have to copy settings over...
cookie.Value = encTicket;
HttpContext.Current.Response.Cookies.Add(cookie);
return encTicket.Length;
}
public void SignOut()
{
FormsAuthentication.SignOut();
}
public bool IsAuthorized()
{
return HttpContext.Current.User != null &&
HttpContext.Current.User.Identity != null &&
HttpContext.Current.User.Identity.IsAuthenticated;
}
public void SetUserOnApplication_AuthenticateRequest<T>(HttpContext context)
{
PrincipalUser principal = null;
ICookieUserData userData = null;
// Extract the forms authentication cookie
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = context.Request.Cookies[cookieName];
if (null == authCookie)
{
// There is no authentication cookie.
return;
}
var nameIdentity = HttpContext.Current.User.Identity.Name;
if(string.IsNullOrEmpty(nameIdentity)) {
return;
}
if(HttpContext.Current.Cache[nameIdentity] ==null) {
FormsAuthenticationTicket authTicket = null;
try {
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch (Exception ex) {
// Log exception details (omitted for simplicity)
return;
}
if (null == authTicket) {
// Cookie failed to decrypt.
return;
}
userData = (ICookieUserData)new JavaScriptSerializer().Deserialize<T>(authTicket.UserData);
// When the ticket was created, the UserData property was assigned a
// pipe delimited string of role names.
string[] roles = authTicket.UserData.Split('|');
// Create an Identity object
//FormsIdentity id = new FormsIdentity(authTicket);
// This principal will flow throughout the request.
//PrincipalUser principal = new PrincipalUser(id, roles);
} else {
userData = (ICookieUserData)HttpContext.Current.Cache[nameIdentity];
}
principal = new PrincipalUser(userData);
// Attach the new principal object to the current HttpContext object
context.User = principal;
}
public void CheckAuthorization()
{
if (!this.IsAuthorized()) throw new Exception("Access not allowed");
}
public void CheckAuthorizationForUrl(string url)
{
AuthContextConfiguration.CheckAuthorizationForUrl(url);
if (AuthContextConfiguration.CheckRequiredAuth() && !this.IsAuthorized()) throw new Exception("Access not allowed");
}
}
public class PrincipalUser : IPrincipal
{
private ICookieUserData _userData;
private GenericIdentity _identity;
public PrincipalUser(ICookieUserData userData)
{
_identity = new GenericIdentity(userData.Name);
_userData = userData;
}
public IIdentity Identity
{
get
{
return _identity;
}
}
public ICookieUserData UserData
{
get
{
return _userData;
}
}
public bool IsInRole(string role)
{
return _userData.Role.Contains(role);
}
}
public interface ICookieUserData
{
string Name { get; set; }
string Role { get; set; }
}
}
And now the problem is when I debug from [TestMethod] and I go into method with debugging (F10) and putted breakpoint in the method in HomeController.cs I see this System.Web.HttpContext.Current is every time null! What's the problem? I use Moq.
HttpContextfor that very reason. instead encapsulate that behind abstractions that can be mocked when testing in isolation.ie AuthenticationProvider _authProvider = new AuthenticationProvider(this.HttpContext);