如何将userId传递到ASP.NET MVC模型中?

3

我已经进行了彻底的搜索,但无法找到任何解决我面临的场景的答案(奇怪的是,因为我认为这是一个很常见的事情)。

背景

我正在使用ASP.NET MVC 4和Entity Framework 5 Code First创建应用程序。对于这个问题,可以将其视为具有帖子和用户的博客应用程序。

项目

帖子模型要求每个帖子都有相应的UserId。

使用ASP.NET MVC 4 Membership可以轻松找到已登录用户的用户名:

User.Identity.Name

这并不理想,我们需要ID,但是可以使用以下查询在数据库中搜索名称并获取ID:

db.UserProfiles.Single(a => a.UserName == User.Identity.Name);

问题

问题出现在尝试创建帖子时。Model.IsValid为false,因为未从视图传递任何UserId。显然,因为不希望用户输入他们的ID。

我已经尝试将ID值放入ViewBag并在视图中使用@Html.Hidden()字段,但我没有成功。 Model.IsValid始终返回false。

这些信息应该通过create view输入吗?还是应该直接在控制器中完成?这是一个相当令人沮丧的问题,因为我有这些信息,只需要弄清如何将其传递到模型中。

控制器代码

这基本上只是默认的脚手架代码。注释掉的代码是我尝试直接从控制器设置模型值的方式,但那只是试错。

    //
    // POST: /Post/Create

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Post post)
    {
        if (ModelState.IsValid)
        {
            //var userId = db.UserProfiles.Single(a => a.UserName == User.Identity.Name);
            //post.User.UserId = userId.UserId;
            db.Posts.Add(post);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(post);
    }

1
请展示你的代码:控制器动作、视图和模型。 - user571874
展示生成的 HTML 标记,以显示您的隐藏 userId 属性。 - user571874
3个回答

3

小心隐藏字段。任何人都可以在该字段中放置任何值(例如,他们可以伪造另一个用户)。最好在登录时将ID缓存到会话中,并使用该值。


隐藏字段非常容易受到注入攻击。任何人都可以操纵它们,因此不应将其视为“安全”。 - Travis J

2

这是一个典型的案例,您希望创建一个 EditModel 作为视图和控制器层之间的数据传输对象(DTO)。

创建一个类 BlogPostEditModel,该类具有在创建新博客文章时需要用户填写的所有属性。然后,将此类型(例如使用 AutoMapper)映射到您的 BlogPost 实体,并填写用户 ID。

如果要使用内置的验证,例如 Model.IsValid(),请在 DTO 上放置数据注释属性。


另一种解决方案是创建一个操作过滤器来为您设置值。 - Tomas Aschan
在我看来,你的评论应该是你的答案。我不明白为什么人们坚持使用他们的数据库映射实体作为视图模型,但如果他们这样做,至少可以在他们的操作上配对一个过滤器。 - Travis J
谢谢你的输入Tomas。我会研究创建中介模型。 - garrdb
@TravisJ:将注释保留为注释而不是放在答案中的主要原因是,我认为创建DTO比使用操作过滤器更好。 - Tomas Aschan

2
老实说,我会通过控制器分配值。如果有人通过Firebug篡改您的HTML,他们实际上可以在提交到表单之前更改ID。我会从创建视图中删除它,并从控制器提交。

我更喜欢在控制器中完成这个操作。HTML 不够安全,不能信任它来处理像用户 ID 这样重要的信息。 - Travis J
这绝对是我在提问之前试图实现的最理想选项。我尝试过通过访问对象并将userId字段设置为正确的值来实现这一点,如 post.User.UserId = userId.UserId; 这样做是在控制器中设置模型值的正确方式吗? - garrdb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接