从ASP.NET MVC控制器构造函数访问时,IPrincipal属性为null



下面的示例代码抛出带有消息Object reference not set to an instance of an object.NullReferenceException。错误是指User属性为null

基本控制器

public class BaseController : Controller
{
public string UserName
{
get
{
return User.Identity.Name;
}
}
}

主控制器

[Authorize]
public class HomeController : BaseController
{
private string username { get; set; }
public HomeController()
{
username = UserName;
}
// GET: Home
public ActionResult Index()
{
ViewBag.UserName = username;
return View();
}
}

另一方面,如果直接在操作内部访问UserName属性,则它可以正常工作。因此,如果将代码更改为:,则该代码有效

主控制器

[Authorize]
public class HomeController : BaseController
{
// GET: Home
public ActionResult Index()
{
ViewBag.UserName = this.UserName;
return View();
}
}

有什么想法吗?

更新:

因此,真正的问题是HttpContext在控制器的构建过程中不可用。我真的很奇怪为什么?有什么解释吗?另外,如果我需要使用构造函数DI来实例化依赖类,而依赖类又需要知道当前登录的用户,例如:

[Authorize]
public class HomeController : BaseController
{
private IMyService service;
public HomeController(IMyService service)
{
this.service = service;
this.service.UserName = UserName;
}
// GET: Home
public ActionResult Index()
{
// use service here ...
return View();
}
}

您无权访问构造函数中的HttpContext。如果你想在一个地方添加这样的检索逻辑,你可以用其中一种方法。


直接呼叫基本控制器

从基本控制器访问UserName属性,无需将其重置为派生控制器上的属性或字段。

[Authorize]
public class HomeController : BaseController
{
// GET: Home
public ActionResult Index()
{
ViewBag.UserName = UserName;
return View();
}
}

挂钩到OnActionExecuting而不是ctor

设置Controller.OnActionExecuting中的值,而不是构造函数,因为此时您可以访问HttpContext。将override添加到方法中以执行此操作。


扩展方法

请改为添加方法扩展。我更喜欢这种方法,因为我不喜欢控制器继承,只是从标准Mvc控制器继承。

public static class ControllerExtension {
public static string UserName(this Controller controller) {
return controller.User.Identity.Name;
}
}

你的代码变成

[Authorize]
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
ViewBag.UserName = this.UserName();
return View();
}
}

编辑

。。。其中构造函数DI用于实例化参数,该参数又具有需要设置的UserName属性。。。

您可能希望将HttpContextBase实例注入到您的服务中,并让它以这种方式检索经过身份验证的用户名。您不希望Controller实例需要向服务提供用户名,因为这会创建紧密耦合的代码并破坏SoC(关注点分离)。

class MyService : IMyService
{
public string UserName {get;}
// inject HttpContextBase
public MyService(HttpContextBase context){
this.UserName = context.User.Identity.Name;
}
}

这是因为构造函数中没有HttpContext。只有在控制器实例化之后,才会分配User属性。

尝试在那里使用System.Web.HttpContext.Current.User

相关内容

  • 没有找到相关文章