我有一个购物篮,其中包含用户选择的项目并存储在会话变量中。我希望在每个视图上显示关于篮子状态的各种值,即篮子:1,但我只能看到如何将其传递给单个入口点的视图。我将如何使用此列表初始化每个视图?
问问题
56 次
2 回答
0
child action
你可以在你的布局中渲染一个。子动作的想法是它可以与主动作并行执行一些逻辑。
例如,您可以拥有以下控制器:
public class ShoppingBasketInfoController: Controller
{
[ChildActionOnly]
public ActionResult Index()
{
var model = Session["info"] as ShoppingInfoViewModel;
return PartialView(model);
}
}
然后你就会有一个对应的局部视图(~/Views/ShoppingBasketInfo/Index.cshtml
):
@model ShoppingInfoViewModel
<div>
You have @Html.DisplayFor(x => x.NbProducts) in your basket
</div>
然后你可以在你的布局中找到一个合适的地方来呈现这个动作:
@Html.Action("Index", "ShoppingBasketInfo")
现在,您的所有视图都将在指定位置显示此信息,而无需担心此信息来自何处、如何存储或使用什么视图模型。主要动作完全独立。
我用[ChildActionOnly]
属性修饰了子操作,以确保永远不会通过来自客户端的正常 HTTP 请求访问此操作,例如/ShoppingBasketInfo/Index
. 它只能在主要执行动作的上下文中使用。
于 2013-01-17T13:50:15.527 回答
0
您最好的选择可能是基本控制器、基本视图模型、接口和动作过滤器的组合。
// Interface. To be implemented by model and controller.
public interface IHoldABasket
{
Basket Basket { get; set; };
}
// Base view model. Has a basket as public property.
public BaseBasketViewModel : IHoldABasket
{
public Basket Basket { get; set; }
}
// Base controller model. Also has a basket.
public BaseController : Controller, IHoldABasket
{
public Basket Basket { get; set; }
public BaseController()
{
AttemptBasketLoad();
}
private void AttemptBasketLoad()
{
// Replace the SomeMethodToLoadBasket with whatever method you use
// to retrieve a basket.
Basket = SomeMethodToLoadBasket();
}
}
// Action Filter
public class BasketAwareAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// If controller can hold basket AND model can hold basket
if (filterContext.Controller is IHoldABasket
&& filterContext.Controller.ViewData.Model is IHoldABasket)
{
// Copy basket from controller into model.
// Will now be accessible through Basket property on model.
((IHoldABasket)filterContext.Controller.ViewData.Model)
.LoggedInUser
= ((IHoldABasket)filterContext.Controller).LoggedInUser;
}
base.OnActionExecuted(filterContext);
}
}
这就是排序的基础设施。让我们看一个实际的例子。您可能有一个 ProductListViewModel。那应该从基本视图模型类继承。
首先,确保您的 ProductListViewModel 继承自 BaseBasketViewModel。
public class ProductListViewModel : BaseBasketViewModel
{
}
由于继承,您的视图模型包含一个篮子对象并实现 IHoldABasket 接口。
您的控制器将从 BaseController 继承。
public class ProductController : BaseController
{
}
控制器方法如下所示。
[BasketAware]
public ViewResult Products(int page = 1)
{
// Load VM that implements IHoldABasket
// Really contrived, I know... :P
var vm = new ProductListViewModel() { Results = productServices.Search() };
return View(vm);
}
应该是这样的。幕后发生的事情是
- 基本控制器尝试加载一个篮子,如果找到一个则将其存储
- Controller 和 Model 继承了一个通用接口,使得从控制器到模型的自动复制更容易实现。
- 动作过滤器在最后一分钟加载。如果控制器和模型都可以容纳一个篮子(例如两个工具
IHoldABasket
),则篮子从控制器复制到模型。 - 从 BaseBasketViewModel 派生的所有视图模型都将具有一个名为 Basket 的公共属性。
于 2013-01-17T14:01:17.543 回答