- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我刚刚阅读了不止一篇,但没有找到解决我问题的方法。我已经使用 FrameWork 4.5 创建了 WebApi + MVC 和单元测试项目。我有这个 HomeController.cs 用这个方法:
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();
}
}
}
HomeControllerTest.cs 的代码如下:
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);
}
}
}
AuthenticationProvider.cs 类在这里:
/* 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; }
}
}
现在的问题是,当我从 [TestMethod] 调试并进入调试方法 (F10) 并在 HomeController.cs 的方法中放置断点时,我看到了这个 System.Web.HttpContext.Current 每次都是空的!有什么问题?我使用最小起订量。
最佳答案
System.Web.HttpContext.Current
由在单元测试期间不存在/不活动的 IIS 填充。因此 null。出于这个原因,不要将您的代码与 HttpContext
紧密耦合。而是将其封装在可以在隔离测试时模拟的抽象背后。
撇开糟糕的设计不谈,对于您的特定设计,您正试图访问 Controller 外部的静态依赖项。如果像当前测试中演示的那样伪造 Controller 的上下文,则访问 Controller 的上下文而不是调用静态上下文。
//... code removed for brevity
var _authProvider = new AuthenticationProvider(this.HttpContext);
//... code removed for brevity
除此之外, Controller 的设计应该重构为明确依赖于抽象而不是具体化。
例如,这里是提供者的抽象
public interface IAuthenticationProvider : IFormsAuthentication {
void CheckAuthorizationForUrl(string url);
//...other members
}
public class AuthenticationProvider : IAuthenticationProvider {
//...
}
Controller 应该通过构造函数注入(inject)明确地依赖于此
public class HomeController : Controller {
private readonly IAuthenticationProvider authProvider;
public HomeController(IAuthenticationProvider authProvider) {
this.authProvider = authProvider;
}
public ActionResult Index() {
ViewBag.Title = "Home Page";
var guidAccount = "xxxxxxxx-xxxx-xxxx-xxxx-422632e0bd95";
var userData = new CookieUserData(guidAccount) { GuidAccount = guidAccount };
authProvider.CheckAuthorizationForUrl("http://pippo");
return View();
}
}
如果使用依赖注入(inject),IAuthenticationProvider
实现应该配置为在运行时使用框架的 DependencyResolver
注入(inject) Controller ,但现在可以在测试 Controller 时替换隔离,以免与框架实现问题耦合。
[TestClass]
public class HomeControllerTest {
[TestMethod]
public void Index(){
// Disposizione
var authMock = new Mock<IAuthenticationProvider>();
var controller = new HomeController(authMock.Object);
// Azione
ViewResult result = controller.Index() as ViewResult;
// Asserzione
Assert.IsNotNull(result);
Assert.AreEqual("Home Page", result.ViewBag.Title);
}
}
关于c# - 为什么 HttpContext 为空?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49687708/
我是 HangFire 的初学者,期待使用 HangFire 每月在我的网络应用程序中调用一些操作。但是这些操作需要 HttpContext。 那么我的问题是:有没有办法在 HangFire 项目中添
是 HttpContext.Current.User 在全局 asax 中与 不同HttpContext.User 在 Action 方法中?我为用户分配了一些角色,但他们似乎迷路了。 下面的代码显示
我不明白 HttpContext.Handler 和 HttpContext.CurrentHandler 之间有什么区别。 任何人? 最佳答案 微软: CurrentHandler 属性引用的当前正
这两种获取当前 asp.net 请求异常的方法之间有什么实际区别吗? MSDN 说 HttpContent.Error 返回第一个错误,而 GetLastError() 显然是最后一个错误,但我似乎无
我正在使用 httphandler。在 ProcessRequest 中传递的 HttpContext 是否引用了 HttpContext.Current?使用它们有什么不同吗? 最佳答案 是的,两者
我目前正在处理一些遗留代码,其中 HttpContext.Current.User 属性在 MVC Controller 方法中用于对当前用户执行一些基本授权。通过阅读文档,还有一个 HttpCont
我们正在迁移应用程序以使用 IIS7 集成模式。在设计为在 HTTP 请求上下文或不在上下文中工作的库代码中,我们通常有这样的代码: if (HttpContext.Current != null &
我想知道 Web API Controller 中的 HttpContext.Request.Path 和 HttpContext.Request.PathBase 有什么区别?我阅读了文档但不明白有
我真的无法找出 C#/.NET 中这两种方法之间的真正区别。 事实上他们应该做同样的 Action ! 最佳答案 第一个包含一个安全的读/写存储位置,可以在整个 HTTP 请求中使用。例如,您可以使用
想知道 - HttpContext.Response.Cache 和 HttpContext.Current.Cache 对象有什么区别?以及在 Asp.net MVC Web 应用程序中应该使用什么
我的 Controller 有这样声明的用法(不确定顺序是否重要) using System; using System.Collections.Generic; using System.Linq;
我的团队正在开发一个基于 ASP.NET Core Web 应用程序 (.NET Framework) 模板构建的新项目。由于遗留原因,我们有另一个项目构建在 System.Web 上,并通过 Htt
如果我想存储一些对象以在页面和 session 之间共享,我应该使用哪一个? HttpContext.Current.ApplicationInstance.Application 或 HttpCon
这 2 个似乎有些含糊不清。我在整个项目中交替使用它们,唯一的原因是我不知道何时使用其中一个。 在什么情况下一个为真而另一个为假? 如果我只使用 ASP.NET Identity 来对用户进行身份验证
我正在开发一个 ASP.NET web 应用程序,我想实现缓存,所以我想知道 HttpContext.Current.Cache.Insert 和 HttpContext.Current 之间的区别.
这两个属性有什么区别? 我可以使用 HttpContext.Items 而不是 HttpContext.Features 在中间件之间共享数据。我看到的唯一区别是我告诉 Items 一个键,它给了我一
微软的HttpContext.Current.Request.ServerVariables[“REMOTE_ADDR”]正在为远程客户端返回ipv6。但是,我需要将此数据用于一个会话日志表,其中的C
if (HttpContext.Current.Request.Cookies.AllKeys.Contains("myCookie") && !String.IsNullOrEmpty(Ht
我有一个项目作为引用添加到 System.Web。 但是,它似乎无法获取 HttpContext。这样做: Imports System.Web _ApplicationBase = HttpCont
我创建了这个类来从请求中获取 Header 值。 public class AuthenticationHeader { private static IHttpContextAccesso
我是一名优秀的程序员,十分优秀!