Razor 无论站点的入口点是什么,都希望用列表初始化每个视图
我有一个购物篮,它容纳用户选择的项目,并存储在会话变量中。我希望它能在关于basket状态的每个视图上显示不同的值,即basket:1,但我只能看到如何在单个入口点将其传递给视图。如何使用此列表初始化每个视图?您可以在布局中渲染。子操作的概念是,它可以与主操作并行执行某些逻辑 例如,您可以使用以下控制器:Razor 无论站点的入口点是什么,都希望用列表初始化每个视图,razor,asp.net-mvc-4,shopping-cart,Razor,Asp.net Mvc 4,Shopping Cart,我有一个购物篮,它容纳用户选择的项目,并存储在会话变量中。我希望它能在关于basket状态的每个视图上显示不同的值,即basket:1,但我只能看到如何在单个入口点将其传递给视图。如何使用此列表初始化每个视图?您可以在布局中渲染。子操作的概念是,它可以与主操作并行执行某些逻辑 例如,您可以使用以下控制器: public class ShoppingBasketInfoController: Controller { [ChildActionOnly] public ActionR
public class ShoppingBasketInfoController: Controller
{
[ChildActionOnly]
public ActionResult Index()
{
var model = Session["info"] as ShoppingInfoViewModel;
return PartialView(model);
}
}
然后您将有一个相应的局部视图(~/Views/ShoppingBasketInfo/Index.cshtml
):
现在,所有视图都将在指定位置显示此信息,而不必担心此信息来自何处、如何存储或使用何种视图模型。主要动作是完全独立的
我已经用
[ChildActionOnly]
属性修饰了子操作,以确保此操作永远不会通过客户端的正常HTTP请求访问,例如使用/ShoppingBasketInfo/Index
。它只能在主执行操作的上下文中使用。您的最佳选择可能是基本控制器、基本视图模型、接口和操作过滤器的组合
// 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
{
}
由于继承,视图模型包含一个basket对象并实现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);
}
应该是这样。引擎盖下发生的事情是
- 基本控制器尝试加载一个篮子,如果找到,则将其存储
- 控制器和模型继承了一个公共接口,使得从控制器到模型的自动复制更容易实现
- 动作过滤器在最后一分钟加载。如果控制器和模型都可以容纳一个篮子(例如,两个机具
),则篮子将从控制器复制到模型IHoldABasket
- 所有从BaseBasketViewModel派生的视图模型都将有一个名为Basket的公共属性
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);
}