ASP.NET MVC:在页面之间传递值

时间:2010-08-18 01:56:46

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

tldr>一旦选择了客户,所有其他控制器如何始终在该客户的“上下文”中执行其操作,而无需手动传递ID?

我正在试图找出“正确”的方法来处理整个控制器(或更多)都依赖于前一个控制器的想法的情况。例如,假设您正在构建某种客户管理系统。可能有各种客户功能,可能位于CustomerController上。但是当你进入订单管理时,你可能想要一个OrderController。

如果您只有一个OrderController,您的方法可能如下所示:

public ActionResult Edit(string id){...}

id是订单的ID,对吧?在我需要回到客户的时候,我有点失落。这就像发生的所有行为的“背景”都在客户中。您可以通过始终将客户ID添加到操作(URL)来执行此操作:

http://site.com/Orders/Edit/1234?customerId=abc

但是,抓住这个价值并将其干扰到每一个行动似乎都变得相当繁琐。有像Session这样的选项,但这看起来很草率。

这样做的正确方法是什么?

4 个答案:

答案 0 :(得分:3)

您可以通过在会话周围编写一个包装器来减少一般会话的不稳定性,这会暴露强类型的属性。

//Sloppy weak typing:
int userId = (int)HttpContext.Current.Session["UserId"];

//Strongly typed goodness
int userId = SessionWrapper.UserId;

答案 1 :(得分:0)

会话是一个存储这类东西的地方。

您还可以使用可扩展的分布式缓存(http://msdn.microsoft.com/library/cc645013.aspx)。来自上面链接的示例代码

// CacheFactory class provides methods to return cache objects
// Create instance of CacheFactory (reads appconfig)
DataCacheFactory fac = new DataCacheFactory();
// Get a named cache from the factory
DataCache catalog = fac.GetCache("catalogcache");
//-------------------------------------------------------
// Simple Get/Put
catalog.Put("toy-101", new Toy("thomas", .,.));
// From the same or a different client
Toy toyObj = (Toy)catalog.Get("toy-101");
// ------------------------------------------------------
// Region based Get/Put
catalog.CreateRegion("toyRegion", true);
// Both toy and toyparts are put in the same region
catalog.Put("toy-101", new Toy( .,.), "toyRegion");
catalog.Put("toypart-100", new ToyParts(…), "toyRegion");
Toy toyObj = (Toy)catalog.Get("toy-101", "toyRegion");

答案 2 :(得分:0)

将会话信息序列化为加密会话cookie是另一种解决方案。好处是能够避免消耗服务器资源并实现相同的目标:

    private void setSessionCookie() {
        HttpCookie ck = new HttpCookie(XConstants.X_SESSION_COOKIE_KEY) {
            Expires = DateTime.Now.AddMinutes(_sessionInfo.SessionTimeoutMinutes)
        };
        DateTime now = DateTime.UtcNow;
        _sessionInfo.SessionLastValidatedAt = now;
        ck.HttpOnly = true; // server-only cookie
        ck["LastCheck"] = now.ToString(XConstants.XDATEFORMAT);
        ck["Content"] = new Cipher().Encrypt(Serializer.Serialize(_sessionInfo).OuterXml,
            ConfigurationManager.AppSettings[XConstants.X_APPKEY_KEY]);
        System.Web.HttpContext.Current.Response.Cookies.Add(ck);
    }

答案 3 :(得分:0)

如果您确实希望避免将值存储到会话中,则可以使用处理该值的操作过滤器。我曾经使用过这种方法,它是这样的:

  1. 创建一个包含值的占位符的新路由,例如:客户ID。
  2. 选择客户后,将ID添加到路由以进行下一次GET或POST呼叫。
  3. 创建一个操作过滤器,该过滤器从路径读取id并在操作发生之前将其添加到操作参数(OnActionExecuting)。完成操作后,此相同的过滤器会将操作参数中的id添加回路由数据(OnActionExecuted)。
  4. 可以在控制器级别使用此新操作过滤器。
  5. 现在您的客户ID很容易保留在URL中,即使您没有手动将其添加到所有链接。如果需要在操作方法中使用customer id,只需添加具有正确名称的参数即可。即使您不将其作为参数,它也会保留在动作方法调用上。

    如果您想更进一步,在新的操作过滤器中,您可以从数据库中获取数据并将其添加到操作参数,而不是仅添加ID。这样您就可以进一步简化操作方法。