从父视图向许多部分视图提供ID而不暴露敏感ID

时间:2012-04-13 14:30:35

标签: c# asp.net-mvc asp.net-mvc-3

我们正在使用友好的名称URL路由方案。基本上使用Principal Identity和友好名称的组合,可以在内部将其映射回身份(人员ID)。所以这样的路线:

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

会映射到这样的网址:

    Adam/Products/List

这一切都很好,并且抽象出了所需的指定人员的内部ID。

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

我已经考虑了一段时间了,我有两种解决方案:

  1. 将“友好名称”传递给每个返回部分视图的控制器操作方法,在内部,方法必须对当前登录的标识和友好名称进行查找。这将给我PersonID,然后我可以从那时开始有效地查询。这个apporach的唯一问题是,由于多个部分视图,我将查询当前登录的身份和每个部分视图调用的友好名称,这是innefficeint,我觉得我只需要编写一次此代码。

  2. 以某种方式查询视图并获取PersonID,以便将其传递给每个@ Html.Action调用,这样部分视图控制器方法就不必自己进行查找,从而节省了到数据库的往返行程共享信息。这个问题是我不确定在视图中使用我们在应用程序其余部分使用的DI的方法来做这个清理。

  3. 非常感谢任何关于接近的想法。

    谢谢,

    亚当

3 个答案:

答案 0 :(得分:1)

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

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

然后,您可以直接将其传递给父级的部分视图,而不会触及客户端或必须将参数传递给任何控制器。

<强>更新

如果您想在那里进行工作而不需要往返数据库,也可以从Controller访问会话变量。

修改

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

例如,如果您的控制器执行:

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

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

有很多方法可以解决这个问题。使用@ Html.HiddenFor(m =&gt; m.ID) 这将把属性放在渲染的HTML中,如果它确实是一个敏感的信息,那就很糟糕了。

或者您可以在每次后续回发时重建视图模型。

希望这有帮助

答案 1 :(得分:0)

正如马克所说,我可以在会议上处理这个问题,但我已经按照他在更新中所说的那样使用了模型。如果父视图控制器操作采用友好名称,则可以执行查找,将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);
    }
}

我之前尝试过我之前的想法,但我一定有错误,因为ViewModel属性显示在URL中,这正是我试图摆脱的。无论如何,我希望这可以帮助其他任何可能想要做类似事情的人。如果您有任何疑问,请告诉我。

谢谢,

亚当

答案 2 :(得分:0)

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

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

您还可以使用模型绑定器将理解的[ReadOnly]属性,而不是分配给该属性。

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

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

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/,则可以轻松使用。