Asp.net mvc 4 ASP.NET 4.5和Web API中的URL重写

Asp.net mvc 4 ASP.NET 4.5和Web API中的URL重写,asp.net-mvc-4,asp.net-mvc-routing,asp.net-web-api,Asp.net Mvc 4,Asp.net Mvc Routing,Asp.net Web Api,我们有一个长期运行的ASP.NET web表单应用程序,它诞生于.NET 1.1/IIS6时代。我们现在在.NET4.5/IIS7上,但是我们没有对MVC做任何事情 我们向客户提供一个目录,并为他们提供一个他们可以使用的URL: www.ourhost.com/customername 使用我们开发的自定义IHTTP模块,我们从URL中提取“customername”,在数据库中查找客户。然后,该客户的ID存储在页面的上下文*中,并被站点上的几乎所有页面用于为该客户定制内容。在这个过程之后,上

我们有一个长期运行的ASP.NET web表单应用程序,它诞生于.NET 1.1/IIS6时代。我们现在在.NET4.5/IIS7上,但是我们没有对MVC做任何事情

我们向客户提供一个目录,并为他们提供一个他们可以使用的URL:

www.ourhost.com/customername
使用我们开发的自定义IHTTP模块,我们从URL中提取“customername”,在数据库中查找客户。然后,该客户的ID存储在页面的上下文*中,并被站点上的几乎所有页面用于为该客户定制内容。在这个过程之后,上面的URL将被重写并处理为

www.ourhost.com/index.aspx
index.aspx可以通过其上下文访问客户的ID,它可以完成自己的任务

这非常有效,我们支持数千名客户。重写逻辑相当复杂,因为它验证客户帐户,如果客户无效,则重定向到“嗯-哦”页面,如果客户未付款,则重定向到其他“查找经销商”页面,等等

现在我想构建一些WebAPI控制器,MVC风格的重写让我担心。我看到了许多例子,其中重写使URL像这样工作:

www.ourhost.com/api/{controller}
但我仍然需要这些web api“调用”在客户上下文中发生。我们的页面在JSON/AJAX异步调用方面变得越来越复杂,但在回答这些调用时,我仍然需要客户上下文。我想的网址是

www.ourhost.com/customername/api/{controller}
但是我很难理解如何配置路由来实现这一点,并让它与我们的IHttpModule很好地配合使用

这可能吗


*更新:当我说“存储在页面上下文中”时,我指的是与每个web请求相关联的HttpContext,其中包括一个字典,我可以在其中存储一些页面/请求特定的数据。

我可以看到您问题的答案有两部分

跨多个请求维护用户信息 一般来说,MVCAPI应用程序将是无状态的,即在请求之间不保留当前用户的会话状态。这就是我在编写RESTFul API时所学到或被多次宣传的东西

也就是说,您可以通过将以下内容添加到global.asax.cs来启用MVC Web API中的会话状态

    protected void Application_PostAuthorizeRequest()
    {
        // To enable session state in the WebAPI.
        System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required);
    }
在请求中授权客户 正如您在请求URL中所示,您可以添加客户名称,然后捕获该名称,并将其传递到当前http模块调用以根据请求进行授权的同一例程。您可以使用MVC过滤器来实现这一点

首先,使用类似的URL模式在WebApiConfig.cs中捕获您的客户名称,类似这样

        config.Routes.MapHttpRoute(
            name: "WithCustomerApi",
            routeTemplate: "api/{customername}/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
[WebApiAuthentication]
public class BaseApiController : ApiController
{
}
然后将ActionFilter添加到API控制器,该控制器处理每个请求,检查当前会话信息,如果需要,调用授权/客户查找代码,然后保存到会话状态以供以后使用。或者,如果客户没有好的信息,可以发送到新的MVC路线

因此,您将添加一个类似这样的属性

        config.Routes.MapHttpRoute(
            name: "WithCustomerApi",
            routeTemplate: "api/{customername}/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
[WebApiAuthentication]
public class BaseApiController : ApiController
{
}
然后创建一个看起来像这样的操作过滤器(注意,我没有测试过这个,只是针对如何操作的模式进行了测试)

如果您创建了一个新的MVC5WebAPI应用程序,并添加了这些额外的内容,并将过滤器放在默认值控制器上,那么您应该能够看到这个运行作为一个可能的解决方案的演示

如果一切正常,这将回显客户名称

[WebApiAuthentication]
public class ValuesController : ApiController
{
    // GET api/values
    public IEnumerable<string> Get()
    {
        var session = HttpContext.Current.Session;

        if (session != null)
        {
            return new string[] {"session is present", "customer is", session["CustomerName"].ToString()};
        }

        return new string[] { "value1", "value2" };
    }

}
[WebAPI身份验证]
公共类值控制器:ApiController
{
//获取api/值
公共IEnumerable Get()
{
var session=HttpContext.Current.session;
if(会话!=null)
{
返回新字符串[]{“session is present”,“customer is”,session[“CustomerName”].ToString()};
}
返回新字符串[]{“value1”,“value2”};
}
}
我将此作为一个可能的解决方案提供,正如我所说,关于在API中存储会话和授权存在宗教争论,但这不是问题所在。 希望有帮助,
Steve

当您说“存储在页面上下文中”时,您是指
会话
对象,还是直接向某种
Cookie
写入?因为您标记了这个
web api
,所以它有点不同。@特洛伊:谢谢您的评论-我更新了我的问题并进行了澄清。明白了-您正在使用
HttpContext.Current.User
跟踪您登录的用户是谁?如何将其持久化到URL中不包含用户用户名的后续调用中?