从父视图向许多分部视图提供 ID,而不公开敏感 ID

本文关键字:ID 视图 许多 | 更新日期: 2023-09-27 18:30:56

我们使用的是友好的名称 URL 路由方案。基本上,使用主体标识和友好名称的组合,可以在内部映射回标识(人员 ID)。所以像这样的路线:

    routes.MapRoute(string.Empty, "{friendlyname}/Products/{action}", new {controller = "Products", action = "List"});

将映射到如下所示的 URL:

    Adam/Products/List

这一切都工作正常,并抽象掉了命名人员的内部 ID,这也是必需的。

问题是我们的视图由许多部分视图组成。当使用 @Html.Action 方法呈现时,它们最终需要 PersonID,但从 URL 中我们只有"友好名称"。

我已经考虑了一段时间,我想到两个解决方案:

  1. 将"友好名称"传递到返回分部视图的每个控制器操作方法中,该方法必须在内部对当前登录的标识和友好名称进行查找。这会将 PersonID 提供给我,然后我可以从那时起有效地查询。这个应用程序的唯一问题是,由于有多个部分视图,我将查询当前登录的标识和每个部分视图调用的友好名称,这是无效的,我觉得我只需要编写一次这段代码。

  2. 以某种方式在视图中查询并获取 PersonID,以便可以将其传递给每个@Html。Action 调用,以便部分视图控制器方法不必自己执行该查找,从而节省到数据库的往返行程以获得相同的共享信息。这样做的问题是,我不确定使用我们通过应用程序其余部分使用的 DI 在视图中干净地执行此操作的方法。

任何关于方法的想法将不胜感激。

谢谢

亚当

从父视图向许多分部视图提供 ID,而不公开敏感 ID

您可以将 Id 添加到会话变量中,并使用以下命令从视图中访问它:

@{var personId = int.Parse(Session["PersonId"])}

然后,您可以将其直接传递给父级的部分视图,而无需命中客户端或将参数传递给任何控制器。

更新

如果您想在那里执行工作,也可以从控制器访问会话变量,而无需往返数据库。

编辑

如果将属性放在模型中并将其传递给该帖子所在的页面,则该模型将不会在帖子之间保留。

例如,如果您的控制器执行以下操作:

[HttpPost]
public ActionResult DoSomething(ViewModel model)
{
   if(ModelState.IsValid)
   {
       // Logic Here
   }
   return View(model)
}

重新加载页面时,模型将忘记 ID。

有几种方法可以解决这个问题。要么使用 @Html.HiddenFor(m => m.ID)这会将属性放在呈现的 HTML 中,如果它确实是敏感信息,那就不好了。

或者,可以在每次后续回发时重新生成视图模型。

希望这有帮助

正如 Marc 所说,我可以在会议上处理这个问题,但正如他在更新中所说的那样,我已经使用了模型。如果父视图控制器操作采用友好名称,它可以执行查找,将 PersonID 放入模型中,然后任何部分渲染都可以在父视图控制器操作的视图中将模型值传递到它们中。下面显示了一个示例(这是演示代码,但希望它能理解这一点,我永远不会在实际代码中使用静态数据上下文)

家用控制器

public class HomeController : Controller
{
    public ActionResult Index(string friendlyName)
    {
        int pupilId = Data.People.Single(x => x.Name == friendlyName).PersonId;
        HomeIndexViewModel homeIndexViewModel = new HomeIndexViewModel {PupilId = pupilId};
        return View(homeIndexViewModel);
    }
}

主页索引视图

@model SharingInformationBetweenPartials.Web.Models.HomeIndexViewModel
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>    
@Html.Action("DisplayPersonDetail", "Person", new {Model.PersonId})

然后,PersonController 的 DisplayPersonDetail 方法可以使用传入的 PersonId 呈现它希望的相应数据:

public class PupilController : Controller
{
    [ChildActionOnly]
    public ActionResult DisplayPupilDetail(int pupilId)
    {
        Person person = Data.People.Single(x => x.PersonId == pupilId);
        return View(person);
    }
}

确实尝试了我之前的想法,但我一定有问题,因为 ViewModels 属性显示在 URL 中,这就是我试图摆脱的。无论如何,我希望这对其他可能希望做类似事情的人有所帮助。如果您有任何问题,请告诉我。

谢谢

亚当

可以使用

[Bind]属性来指定模型绑定器应在绑定中包含的确切属性,或者对属性使用Exclude参数来排除 PersonId

[HttpPost]
public ActionResult EditPerson([Bind(Exclude = "PersonId")] Person person)
{
    //do domething
}

还可以使用模型绑定程序将理解且不分配给该属性[ReadOnly]属性。

[ReadOnly(true)]
public int PersonId{ get; set; }

但最好的方法是使用单独的 ViewModels:一个仅用于查看,一个用于编辑。

public abstract class Person
{
   public string Name { get; set; }
   public string Surname { get; set; }
}
public class PersonCreateVM : Person
{
   //no PersonId here
}
public class PersonEditVM : Person
{
   public int PersonId{ get; set; }
}

这种方法可能是一种"矫枉过正",但如果正确使用并与AutoMapper一起使用 http://automapper.codeplex.com/它很容易使用。