当函数未从 UI 调用时,用户为 null
本文关键字:用户 null 调用 函数 UI | 更新日期: 2023-09-27 18:33:20
在我的数据库表中,我有一列在保存到数据库之前对值进行操作。操作的逻辑是在开发的后期阶段添加的,在将大量值插入到表中之后。现在,我想编辑表的内容以操作现有内容的值。
我的方法
为表中的所有项调用编辑函数,因为操作逻辑也添加到 EDIT 操作方法中。
当我在循环访问数据库中的内容时调用编辑函数时,我得到一个空引用异常,当我从 UI 使用编辑函数时,该异常不存在。
编辑操作方法
public ActionResult Edit([Bind(Include = "SetValueID,Value,Status,TcSetID,OptionValueID,CreatedOn,CreatedBy,ModifiedOn,ModifiedBy")] SetValue setValue)
{
//Many lines removed for simplicity. all the variables used in the code are assigned.
if (ModelState.IsValid)
{
// Valuestring from another function
setValue.Value = valuestring;
var original = db.SetValue.Find(setValue.SetValueID);
bool modified = original.Value != setValue.Value;
if (modified)
{
var rev = new RevisionHistory();
rev.CreatedOn = original.ModifiedOn;
rev.ModifiedBy = User.Identity.Name; //If modified exception on this line
db.Entry(original).CurrentValues.SetValues(setValue);
db.RevisionHistory.Add(rev);
}
original.ModifiedOn = DateTime.Now;
original.ModifiedBy = User.Identity.Name; //if not modified exception on this line
db.Entry(original).State = EntityState.Modified;
db.SaveChanges();
}
}
对此函数的调用是从 HomeController 进行的。我在 EDIT 方法中注释了所有返回语句,同时从 HomeController 调用它。
例外
对象引用未设置为对象的实例。
问题
为什么从UI调用时编辑工作,没有任何异常,而不是从HomeController调用?
为什么即使我从不同的控制器调用函数,用户也为 null?使用窗口身份验证。如果用户已经过身份验证,如何获取用户名?
编辑 - 添加了如何调用编辑函数
//Home controller (But I have also tried calling the function from a different controller where the call to the method is from the UI
public ActionResult Index()
{
test();
return View();
}
public void test()
{
foreach(var item in db.SetValue.ToList())
{
var setvalcon = new SetValuesController();
setvalcon.Edit(item);
}
}
更新 - 问题的一般概述
可以概括该问题,以便找到在使用 Windows 身份验证时如何定义 User 属性的答案。
控制器是否仅在从 UI 调用 Windows 用户属性时才可以访问该属性?
是否无法访问未通过 UI 调用的函数中的用户属性?
据我所知,关于这个问题的最好的事情是,用户是在调用test
方法的控制器中定义的,但不是在另一个控制器的Edit
中定义的。
当您说只能从 UI 访问 User
属性时,您是部分正确的。正确答案是——
通过 UI 访问 Edit
方法时,它实际上是通过 ASP.Net 控制器初始值设定项管道,该环境负责当前浏览器会话并分配 User
变量。 HttpContext
目前可用。
但是当你像这样创建控制器变量时 -
var setvalcon = new SetValuesController();
setvalcon.Edit(item);
您正在绕过所有这些初始化代码。没有HttpContext
,这只是另一个普通对象,因此它没有填充User
属性。
问题回答:
- 控制器是否仅在从 UI 调用 Windows 用户属性时才可以访问该属性?
=> 是的,绝对正确,因为您正在经历 ASP.Net 管道。但它不仅适用于Windows用户,而且是HttpContext中的所有内容。
- 是否无法访问未通过 UI 调用的函数中的用户属性?
=> 仅当,您手动分配它,否则为否。
更多见解:
基本上,您要实现的是一个非常糟糕的设计。无处可去,记住无处可去,你应该从控制器内部调用控制器,除非它是基方法调用的子类。从另一个控制器内部调用另一个控制器的唯一方法是使用"重定向"方法重定向执行。没有人会阻止你这样调用控制器,但这显示了糟糕的设计原则。
解决你情况的最好办法是这样的——
public class ModelService {
public void Edit(IPrincipal user, SetValue setValue){
setValue.Value = valuestring;
var original = db.SetValue.Find(setValue.SetValueID);
bool modified = original.Value != setValue.Value;
if (modified)
{
var rev = new RevisionHistory();
rev.CreatedOn = original.ModifiedOn;
rev.ModifiedBy = User.Identity.Name; //If modified exception on this line
db.Entry(original).CurrentValues.SetValues(setValue);
db.RevisionHistory.Add(rev);
}
original.ModifiedOn = DateTime.Now;
original.ModifiedBy = User.Identity.Name; //if not modified exception on this line
db.Entry(original).State = EntityState.Modified;
db.SaveChanges();
}
}
然后在两个控制器构造函数中 -
public class ControllerOne : Controller {
private readonly ModelService _modelService
//constructor
public ControllerOne(){
_modelService= new ModelService ();
}
public ActionResult Edit([Bind(Include = "SetValueID,Value,Status,TcSetID,OptionValueID,CreatedOn,CreatedBy,ModifiedOn,ModifiedBy")] SetValue setValue)
{
//Many lines removed for simplicity. all the variables used in the code are assigned.
if (ModelState.IsValid)
{
_modelService.Edit(User, Setvalue);
}
}
//controller 2
public class HomeController: Controller {
private readonly ModelService _modelService
//constructor
public ControllerOne(){
_modelService= new ModelService ();
}
public ActionResult Index()
{
foreach(var item in db.SetValue.ToList())
{
_modelService.Edit(User, item);
}
}
}
您可以从 IoC 容器获得帮助进行依赖注入,这是更好的方法。
从另一个控制器中调用控制器可能会丢失一些数据(作为用户(。我不会花太多精力去理解为什么(除非好奇(,因为这样做可能会被认为是糟糕的设计。(我敢打赌其他一些信息也会丢失,也许是饼干等(。您可以做的更好的事情是将控制器中的逻辑分离到某个服务层中,并使用IPrincipal
用户作为参数调用这些方法。如果您被迫按照您描述的方式执行此操作,则将用户作为参数发送到另一个控制器。
public ActionResult Index()
{
test(User);
return View();
}
public void test(IPrincipal user)
{
foreach(var item in db.SetValue.ToList())
{
var setvalcon = new SetValuesController();
setvalcon.Edit(item, user);
}
}
而控制器
public ActionResult Edit([Bind(Include = "SetValueID,Value,Status,TcSetID,OptionValueID,CreatedOn,CreatedBy,ModifiedOn,ModifiedBy")] SetValue setValue, IPrincipal user = null)
{
var currentUser = User == null? user : User;//or somthing like that
}
没有检查此代码。 但它应该给你一些工作。