0

我们正在使用友好的名称 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 来做这个干净利落的方法。

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

谢谢,

亚当

4

3 回答 3

1

您可以将 Id 添加到会话变量并从视图中访问它:

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

然后,您可以将其直接从 Parent 传递给部分视图,而无需访问客户端或将参数传递给任何控制器。

更新

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

编辑

如果您将属性放在模型中并将其传递到帖子后面的页面,那么模型将不会在帖子之间持续存在。

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

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

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

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

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

希望这可以帮助

于 2012-04-13T14:36:56.557 回答
0

正如 Marc 所说,我可以通过 Session 来处理这个问题,但我已经按照他在更新中所说的那样使用模型。如果父视图控制器操作采用友好名称,它可以进行查找,将 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 中。无论如何,我希望这可以帮助其他可能想做类似事情的人。如果您有任何问题,请告诉我。

谢谢,

亚当

于 2012-04-14T10:08:51.307 回答
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/一起使用,它很容易使用。

于 2012-04-14T10:33:32.160 回答