gpt4 book ai didi

c# - 测试请求的 URL 是否在路由表中

转载 作者:太空狗 更新时间:2023-10-29 21:04:13 24 4
gpt4 key购买 nike

我想测试一个 URL 是否是 Global.asax 中定义的路由的一部分。这是我的:

var TheRequest = HttpContext.Current.Request.Url.AbsolutePath.ToString();
var TheRoutes = System.Web.Routing.RouteTable.Routes;

foreach (var TheRoute in TheRoutes)
{
if (TheRequest == TheRoute.Url) //problem here
{
RequestIsInRoutes = true;
}
}

问题是我无法从路由中提取 URL。我需要更改什么?

最佳答案

The problem is that I can't extract the URL from the route.

我不同意。问题是您期望从路由表中提取 URL 并在外部比较它们。此外,不清楚您希望通过这样做获得什么。

路由会将传入请求与业务逻辑进行比较,以确定它是否匹配。 这是路线的目的。将匹配逻辑移到路由之外不是有效测试,因为您没有测试路由实现的业务逻辑。

Not to mention, it is a bit presumptive to assume that a route can only match a URL and nothing else in the request such as form post values or cookies. While the built in routing functionality only matches URLs, there is nothing stopping you from making a constraint or custom route that matches other criteria.

因此,简而言之,您需要为路由中的业务逻辑编写单元测试。在路由配置之外发生的任何逻辑都应该单独进行单元测试。

有一个great post by Brad Wilson (虽然有点过时)演示了如何对您的路线进行单元测试。我已更新代码以使用 MVC 5 - here is a working demo使用以下代码。

IncomingRouteTests.cs

using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvcRouteTesting;
using System.Web.Mvc;
using System.Web.Routing;

[TestClass]
public class IncomingRouteTests
{
[TestMethod]
public void RouteWithControllerNoActionNoId()
{
// Arrange
var context = new StubHttpContextForRouting(requestUrl: "~/controller1");
var routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);

// Act
RouteData routeData = routes.GetRouteData(context);

// Assert
Assert.IsNotNull(routeData);
Assert.AreEqual("controller1", routeData.Values["controller"]);
Assert.AreEqual("Index", routeData.Values["action"]);
Assert.AreEqual(UrlParameter.Optional, routeData.Values["id"]);
}

[TestMethod]
public void RouteWithControllerWithActionNoId()
{
// Arrange
var context = new StubHttpContextForRouting(requestUrl: "~/controller1/action2");
var routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);

// Act
RouteData routeData = routes.GetRouteData(context);

// Assert
Assert.IsNotNull(routeData);
Assert.AreEqual("controller1", routeData.Values["controller"]);
Assert.AreEqual("action2", routeData.Values["action"]);
Assert.AreEqual(UrlParameter.Optional, routeData.Values["id"]);
}

[TestMethod]
public void RouteWithControllerWithActionWithId()
{
// Arrange
var context = new StubHttpContextForRouting(requestUrl: "~/controller1/action2/id3");
var routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);

// Act
RouteData routeData = routes.GetRouteData(context);

// Assert
Assert.IsNotNull(routeData);
Assert.AreEqual("controller1", routeData.Values["controller"]);
Assert.AreEqual("action2", routeData.Values["action"]);
Assert.AreEqual("id3", routeData.Values["id"]);
}

[TestMethod]
public void RouteWithTooManySegments()
{
// Arrange
var context = new StubHttpContextForRouting(requestUrl: "~/a/b/c/d");
var routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);

// Act
RouteData routeData = routes.GetRouteData(context);

// Assert
Assert.IsNull(routeData);
}

[TestMethod]
public void RouteForEmbeddedResource()
{
// Arrange
var context = new StubHttpContextForRouting(requestUrl: "~/foo.axd/bar/baz/biff");
var routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);

// Act
RouteData routeData = routes.GetRouteData(context);

// Assert
Assert.IsNotNull(routeData);
Assert.IsInstanceOfType(routeData.RouteHandler, typeof(StopRoutingHandler));
}
}

OutgoingRouteTests.cs

using Microsoft.VisualStudio.TestTools.UnitTesting;
using MvcRouteTesting;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

[TestClass]
public class OutgoingRouteTests
{
[TestMethod]
public void ActionWithAmbientControllerSpecificAction()
{
UrlHelper helper = GetUrlHelper();

string url = helper.Action("action");

Assert.AreEqual("/defaultcontroller/action", url);
}

[TestMethod]
public void ActionWithSpecificControllerAndAction()
{
UrlHelper helper = GetUrlHelper();

string url = helper.Action("action", "controller");

Assert.AreEqual("/controller/action", url);
}

[TestMethod]
public void ActionWithSpecificControllerActionAndId()
{
UrlHelper helper = GetUrlHelper();

string url = helper.Action("action", "controller", new { id = 42 });

Assert.AreEqual("/controller/action/42", url);
}

[TestMethod]
public void RouteUrlWithAmbientValues()
{
UrlHelper helper = GetUrlHelper();

string url = helper.RouteUrl(new { });

Assert.AreEqual("/defaultcontroller/defaultaction", url);
}

[TestMethod]
public void RouteUrlWithAmbientValuesInSubApplication()
{
UrlHelper helper = GetUrlHelper(appPath: "/subapp");

string url = helper.RouteUrl(new { });

Assert.AreEqual("/subapp/defaultcontroller/defaultaction", url);
}

[TestMethod]
public void RouteUrlWithNewValuesOverridesAmbientValues()
{
UrlHelper helper = GetUrlHelper();

string url = helper.RouteUrl(new
{
controller = "controller",
action = "action"
});

Assert.AreEqual("/controller/action", url);
}

static UrlHelper GetUrlHelper(string appPath = "/", RouteCollection routes = null)
{
if (routes == null)
{
routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);
}

HttpContextBase httpContext = new StubHttpContextForRouting(appPath);
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "defaultcontroller");
routeData.Values.Add("action", "defaultaction");
RequestContext requestContext = new RequestContext(httpContext, routeData);
UrlHelper helper = new UrlHelper(requestContext, routes);
return helper;
}
}

stub .cs

using System;
using System.Collections.Specialized;
using System.Web;

public class StubHttpContextForRouting : HttpContextBase
{
StubHttpRequestForRouting _request;
StubHttpResponseForRouting _response;

public StubHttpContextForRouting(string appPath = "/", string requestUrl = "~/")
{
_request = new StubHttpRequestForRouting(appPath, requestUrl);
_response = new StubHttpResponseForRouting();
}

public override HttpRequestBase Request
{
get { return _request; }
}

public override HttpResponseBase Response
{
get { return _response; }
}

public override object GetService(Type serviceType)
{
return null;
}
}

public class StubHttpRequestForRouting : HttpRequestBase
{
string _appPath;
string _requestUrl;

public StubHttpRequestForRouting(string appPath, string requestUrl)
{
_appPath = appPath;
_requestUrl = requestUrl;
}

public override string ApplicationPath
{
get { return _appPath; }
}

public override string AppRelativeCurrentExecutionFilePath
{
get { return _requestUrl; }
}

public override string PathInfo
{
get { return ""; }
}

public override NameValueCollection ServerVariables
{
get { return new NameValueCollection(); }
}
}

public class StubHttpResponseForRouting : HttpResponseBase
{
public override string ApplyAppPathModifier(string virtualPath)
{
return virtualPath;
}
}

说完这个,回到你原来的问题。

How to determine if the URL is in the route table?

这个问题有点假设。正如其他人指出的那样,路由表不包含 URL,它包含业务逻辑。更正确的表述问题的方式是:

How to determine if an incoming URL matches any route in the route table?

那么你就上路了。

为此,您需要在路由集合中执行GetRouteData 业务逻辑。这将在每个路由上执行 GetRouteData 方法,直到它们中的第一个返回一个 RouteData 对象而不是 null。如果它们都没有返回RouteData对象(即所有路由都返回null),则表明没有路由与请求匹配。

换句话说,GetRouteDatanull 结果表示没有路由与请求匹配。 RouteData 对象指示匹配的路由之一,它提供必要的路由数据( Controller 、操作等)以使 MVC 匹配操作方法。

所以,简单的判断一个URL是否匹配一个路由,只需要判断操作的结果是否为null即可。

[TestMethod]
public void EnsureHomeAboutMatches()
{
// Arrange
var context = new StubHttpContextForRouting(requestUrl: "~/home/about");
var routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);

// Act
RouteData routeData = routes.GetRouteData(context);

// Assert
Assert.IsNotNull(routeData);
}

另请注意,生成 路由是独立于匹配传入路由的任务。您可以从路由生成传出 URL,但它使用与匹配传入路由完全不同的一组业务逻辑。这个传出 URL 逻辑可以(并且应该)与传入 URL 逻辑分开进行单元测试,如上所示。

关于c# - 测试请求的 URL 是否在路由表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36894210/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com