Some Test:
This is Ture:
[Fact]
public void UriEqualTest()
{
//Act
var uri1 = new Uri("https://www.baidu.com");
var uri2 = new Uri("https://www.baidu.com/");
var boolResult = uri2.Equals(uri1);
//Assert
Assert.Equal(uri1, uri2);
Assert.True(boolResult);//True
}
This is Ture:
[Fact]
public void UriUpperEqualTest()
{
//Act
var uri1 = new Uri("https://wWw.bAidu.com");
var uri2 = new Uri("https://www.baidu.com/");
var boolResult = uri2.Equals(uri1);
var operatorResult = (uri1 == uri2);
//Assert
Assert.Equal(uri1, uri2);
Assert.True(boolResult);//True
}
This is False:
[Fact]
public void UrlEqualTest()
{
//Act
var uri1 = new Uri("https://www.baidu.com/aaaa/bbbb");
var uri2 = new Uri("https://www.baidu.com/aaaa/bbbb/");
var boolResult = uri2.Equals(uri1);
//Assert
Assert.Equal(uri1, uri2);
Assert.True(boolResult);//False
}
This is False:
[Fact]
public void UrlUpperEqualTest()
{
//Act
var uri1 = new Uri("https://www.baidu.com/AAaa/bbbb");
var uri2 = new Uri("https://www.baidu.com/aAAa/bbbb");
var boolResult = uri2.Equals(uri1);
var operatorResult = (uri1 == uri2);
//Assert
Assert.Equal(uri1, uri2);
Assert.True(boolResult);//False
}
This is True:
[Fact]
public void UriUpperEqualAndPathTest()
{
//Act
var uri1 = new Uri("https://www.baiDu.com/aaaa/bbbb");
var uri2 = new Uri("https://www.Baidu.com/aaaa/bbbb");
var boolResult = uri2.Equals(uri1);
//Assert
Assert.Equal(uri1, uri2);
Assert.True(boolResult);//True
}
So,The Host not case sensitive? but path case sensitive??
And I want all Uri dot not case sensitive and dot not case '/',What should I do?
And I want all Uri dot not case sensitive and dot not case '/',What should I do?
And I want all Uri dot not case sensitive and dot not case '/',What should I do?
And in aspnet core mvc, if i use route
[HttpGet("/private/head")] and [HttpGet("/private/HeAd")] and [HttpGet("/private/head/")]
It's error! the error is:
AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:
https://stackoverflow.com/a/2581418/34092 states:
As far as the protocol is concerned, http://example.com/something and
http://example.com/something/ are quite different. Some servers might
redirect you from one to the other if it is implemented in such a way.
As for the pure domain names, it always sends a request ending with a
slash. (The domain name itself is not included in the path section of
an HTTP request, just as Greg Hewgill and the others wrote. It is,
however, included in the headers.)
So, looking at your examples:
var uri1 = new Uri("https://www.baidu.com");
var uri2 = new Uri("https://www.baidu.com/");
They are the same, since always sends a request ending with a slash. They are thus equivalent.
https://serverfault.com/a/261344 states:
Names resolved from DNS are case insensitive. This is important to
prevent confusion.
var uri1 = new Uri("https://wWw.bAidu.com");
var uri2 = new Uri("https://www.baidu.com/");
Thus, the two are equivalent (since they differ only by case and the slash immediately after the host).
var uri1 = new Uri("https://www.baidu.com/aaaa/bbbb");
var uri2 = new Uri("https://www.baidu.com/aaaa/bbbb/");
OK, this seems like the first scenario, but it isn't. The first scenario treats them as equivalent since it is 'pure domain name' (i.e. straight after the host). This is different (i.e. the slash is at the end, not straight after the host), and thus they aren't equivalent (on all web servers). Thus not equal.
var uri1 = new Uri("https://www.baidu.com/AAAaa/bbbb");
var uri2 = new Uri("https://www.baidu.com/aAAa/bbbb");
The path and querystring are case sensitive. Thus these are not equal. Some web servers / programming environments (e.g. ASP.NET MVC) may act case-insensitive, but according to the spec the path and querystring are case sensitive (since some web servers are case sensitive).
var uri1 = new Uri("https://www.baiDu.com/aaaa/bbbb");
var uri2 = new Uri("https://www.Baidu.com/aaaa/bbbb");
The only difference is the case of the host. Thus they are equal.
It's error! the error is: AmbiguousActionException: Multiple actions
matched. The following actions matched route data and had all
constraints satisfied:
This is because ASP.NET MVC is generally not case sensitive. Force case-sensitive routing in ASP.NET MVC may be useful for this part of your problem.
Related
I've been getting non-deterministic test results and decided to delve deeper into the issue. I've ended up on two tests behaving differently based on whether I Debug them, or just use Run. I've managed to magically fix one by deleting and renaming it.
I'm testing my API endpoint for updating usernames via WebApplicationFactory(I'm using Mediator and a RavenDb that I recreate between every test if that makes a difference). The problem test case is User_Can_Not_Update_Username_If_It_Is_Already_Taken(). I'm expecting a Conflict response, but most of the time I'm getting OK. The weirdest thing is that the response varies on where I put my breakpoint:
OK
Conflict.
I've tried clearing Rider cache and looking into my FakeApp not disposing correctly. Trying to Debug before the UpdateUsernameCommandHandlerresults in the Conflict response status code, so I'm really at loss right now.
Here is the code of the test case:
[Fact]
public async Task User_Can_Not_Update_Username_If_It_Is_Already_Taken()
{
// Arrange
using var app = new FakeApp(DatabaseFixture.TestDbName);
var registerUserCommand = new RegisterUserCommand
{
Email = "oleksandr.torianyk#gmail.com"
};
var registerUserStringPayload = JsonConvert.SerializeObject(registerUserCommand);
var registerUserHttpContent = new StringContent(registerUserStringPayload, Encoding.UTF8, "application/json");
var registerUserResponse = await app.Client.PostAsync("/user", registerUserHttpContent);
var initialUpdateUsernameCommand = new UpdateUsernameCommand
{
Id = new Guid(await registerUserResponse.Content.ReadAsStringAsync()),
Username = "All-ToR"
};
var initialUpdateUsernameStringPayload = JsonConvert.SerializeObject(initialUpdateUsernameCommand);
var initialUpdateUsernameHttpContent = new StringContent(initialUpdateUsernameStringPayload, Encoding.UTF8, "application/json");
await app.Client.PutAsync("/user/username", initialUpdateUsernameHttpContent);
var updateUsernameCommand = new UpdateUsernameCommand
{
Id = new Guid(await registerUserResponse.Content.ReadAsStringAsync()),
Username = "All-ToR"
};
var updateUsernameStringPayload = JsonConvert.SerializeObject(updateUsernameCommand);
var updateUsernameHttpContent = new StringContent(updateUsernameStringPayload, Encoding.UTF8, "application/json");
// Act
var response = await app.Client.PutAsync("/user/username", updateUsernameHttpContent);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.Conflict);
}
FakeApp
public class FakeApp : IDisposable
{
private readonly WebApplicationFactory<Startup> _appFactory;
public HttpClient Client { get; }
public FakeApp(string ravenDbName = default)
{
_appFactory = new WebApplicationFactory<Startup>().WithWebHostBuilder(webHostBuilder =>
webHostBuilder.ConfigureServices(services =>
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.Development.json", true)
.AddEnvironmentVariables()
.Build();
services.AddRavenDb(configuration, ravenDbName);
services.AddDependencies();
services.AddMediatR(Assembly.GetExecutingAssembly());
}));
Client = _appFactory.CreateClient();
}
public void Dispose()
{
Client.Dispose();
_appFactory.Dispose();
}
}
Trying to get a basic Elasticsearch Count to work in my netcore API.
Following the documentation I believe this should work-
var node = new Uri(host);
var settings = new ConnectionSettings(node);
settings.DefaultIndex("foo/bar");
var client = new ElasticClient(settings);
var x = await client.CountAsync<dynamic>();
return x.Count;
There is a problem with this, however. The DefaultIndex is encoding slashes (/foo%2Fbar/object/_count). I'm getting a no_index_found_exception exception.
It seems like an easy problem to fix, but I can't find the documentation for this.
How do I prevent uri encoding on my DefaultIndex?
To specify multiple indices as the default index, separate them with a comma. NEST will URI encode the comma
var defaultIndex = "users,posts";
var settings = new ConnectionSettings(new Uri("http://localhost:9200"))
.DefaultIndex(defaultIndex)
.DefaultTypeName("doc");
var client = new ElasticClient(settings);
var searchResponse = client.Search<object>(s => s);
Will send a search request to
POST http://localhost:9200/users%2Cposts/doc/_search
Are there any helper classes available in .NET to allow me to build a Url?
For example, if a user enters a string:
stackoverflow.com
and i try to pass that to an HttpWebRequest:
WebRequest.CreateHttp(url);
It will fail, because it is not a valid url (it has no prefix).
What i want is to be able to parse the partial url the user entered:
Uri uri = new Uri(url);
and then fix the missing pieces:
if (uri.Port == 0)
uri.Port = 3333;
if (uri.Scheme == "")
uri.Scheme = "https";
Does .NET have any classes that can be used to parse and manipulate Uri's?
The UriBuilder class can't do the job
The value that the user entered (e.g. stackoverflow.com:3333) is valid; i just need a class to pick it apart. i tried using the UriBuilder class:
UriBuilder uriBuilder = new UriBuilder("stackoverflow.com:3333");
unfortunately, the UriBuilder class is unable to handle URIs:
uriBuilder.Path = 3333
uriBuilder.Port = -1
uriBuidler.Scheme = stackoverflow.com
So i need a class that can understand host:port, which especially becomes important when it's not particularly http, but could be.
Bonus Chatter
Console application.
From the other question
Some examples of URL's that require parsing:
server:8088
server:8088/func1
server:8088/func1/SubFunc1
http://server
http://server/func1
http://server/func/SubFunc1
http://server:8088
http://server:8088/func1
http://server:8088/func1/SubFunc1
magnet://server
magnet://server/func1
magnet://server/func/SubFunc1
magnet://server:8088
magnet://server:8088/func1
magnet://server:8088/func1/SubFunc1
http://[2001:db8::1]
http://[2001:db8::1]:80
The format of a Url is:
foo://example.com:8042/over/there?name=ferret#nose
\_/ \_________/ \__/\_________/\__________/ \__/
| | | | | |
scheme host port path query fragment
Bonus Chatter
Just to point out again that UriBuilder does not work:
https://dotnetfiddle.net/s66kdZ
If you need to ensure that some string coming as user input is valid url you could use the Uri.TryCreate method:
Uri uri;
string someUrl = ...
if (!Uri.TryCreate(someUrl, UriKind.Absolute, out uri))
{
// the someUrl string did not contain a valid url
// inform your users about that
}
else
{
var request = WebRequest.Create(uri);
// ... safely proceed with executing the request
}
Now if on the other hand you want to be building urls in .NET there's the UriBuilder class specifically designed for that purpose. Let's take an example. Suppose you wanted to build the following url: http://example.com/path?foo=bar&baz=bazinga#some_fragment where the bar and bazinga values are coming from the user:
string foo = ... coming from user input
string baz = ... coming from user input
var uriBuilder = new UriBuilder("http://example.com/path");
var parameters = HttpUtility.ParseQueryString(string.Empty);
parameters["foo"] = foo;
parameters["baz"] = baz;
uriBuilder.Query = parameters.ToString();
uriBuilder.Fragment = "some_fragment";
Uri finalUrl = uriBuilder.Uri;
var request = WebRequest.Create(finalUrl);
... safely proceed with executing the request
You can use the UriBuilder class.
var builder = new UriBuilder(url);
builder.Port = 3333
builder.Scheme = "https";
var result = builder.Uri;
To be valid a URI needs to have the scheme component. "server:8088" is not a valid URI. "http://server:8088" is. See https://www.rfc-editor.org/rfc/rfc3986
Goal: test that a given url returns a given controller function.
In the process, I've broken into the routing system and I can't figure out how to test routes (or, for that matter, find the controller corresponding to the route :-/).
Sample code, which doesn't work:
[Test]
public void kick_the_tires()
{
var rc = new RouteCollection();
Infrastructure.RouteRegistry.RegisterRoutes(rc);
// get the route corresponding to name.
var got = rc["name"];
var expected = //What? foo is an internal type that can't be instantiated.
Assert.AreEqual(foo, frob);
}
edit: Using the linked blog post from Simon for the stub class.
[TestCase("/", "~/", "Home", "Index")]
[TestCase("/", "api/command", "Other", "command")]
internal void stub_mocker(string apppath, string route, string expected_controller,\
string expected_action)
{
var rc = new RouteCollection();
Infrastructure.RouteRegistry.RegisterRoutes(rc);
var httpmock = new StubHttpContextForRouting(
appPath: apppath,
requestUrl: route);
// this always returns null for everything but the Index case.
var routeData = rc.GetRouteData(httpmock);
var controller = routeData.Values["controller"];
var action = routeData.Values["action"];
Assert.AreEqual(expected_controller, controller);
Assert.AreEqual(expected_action, action);
}
All you are testing right now is if the routes are added to the collection, by accessing it by the route name, and not if the expected route will return given a virtual path. You need to obtain the route data as returned by the RouteCollection with a HttpContext.
Best way would be to use a mock or a stub for the HttpContext (or HttpContextBase) and call the RouteCollection's GetRouteData(HttpContextBase) method and inspect the route data.
There is a good example of this in Brad Wilson's blog:
http://bradwilson.typepad.com/blog/2010/07/testing-routing-and-url-generation-in-aspnet-mvc.html
Edit:You cannot get a controller instance from the RouteData itself. However, RouteData should give you enough information to know which controller will be instantiated. For example, if you have a controller at MyProject.Controllers.HomeController with an action Home, this should hold true in your test (using xUnit and Moq):
// Prepare
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();
context.SetupGet(c => c.Request).Returns(request.Object);
context.SetupGet(c => c.Response).Returns(response.Object);
context.SetupGet(c => c.Session).Returns(session.Object);
context.SetupGet(c => c.Server).Returns(server.Object);
request.SetupGet(r => r.HttpMethod).Returns("GET");
request.SetupGet(r => r.PathInfo).Returns(String.Empty);
request.SetupGet(r => r.AppRelativeCurrentExecutionFilePath).Returns("~/Home");
var expectedHandler = typeof (HomeController).GetMethod("Index", Type.EmptyTypes);
var data = RouteTable.Routes.GetRouteData(context.Object);
Assert.NotNull(data);
var handler = (MethodInfo) data.DataTokens["actionMethod"];
Assert.Equal(expectedHandler, handler);
I've had prety good experience with MVCContrib's Testhelper
Take a look at this test of testhelper.
Saves a lot of hassles around stubbing HttpContext etc.
Also if you are on MVC4, have a look at this Nuget package which is a fork for MVC4.
I'm creating a really simple ViewResult subclass called JavaScriptViewResult that, when executing, calls the base implementation and then sets the Content-Type of the response to text/javascript. In trying to unit test this class, I'm running across a slew of difficulties fulfilling all of the dependencies of the ASP.NET MVC stack.
Here is what my unit test, which uses Rhino, looks like so far:
[TestMethod]
public void TestExecuteAction()
{
var request = MockRepository.GenerateMock<HttpRequestBase>();
request.Expect(m => m.Url).Return(new Uri("/Test/JavaScript", UriKind.Relative));
var httpContext = MockRepository.GenerateMock<HttpContextBase>();
httpContext.Expect(m => m.Request).Return(request);
var controller = MockRepository.GenerateMock<ControllerBase>();
var virtualPathProvider = MockRepository.GenerateMock<VirtualPathProvider>();
var routeCollection = new RouteCollection(virtualPathProvider);
routeCollection.MapRoute("FakeRoute", "Test/JavaScript", new { controller = "Test", action = "JavaScript" });
var routeData = routeCollection.GetRouteData(httpContext);
var context = new ControllerContext(httpContext, routeData, controller);
var viewResult = new JavaScriptViewResult();
viewResult.ExecuteResult(context);
Assert.AreEqual("text/javascript", context.HttpContext.Response.ContentType);
}
The latest exception when running the test is a NullReferenceException deep within the bowels of System.Web.Routing.Route.GetRouteData(HttpContextBase httpContext).
How do I set up all of the dependencies for executing a ViewResult? Are there any techniques for making this simpler? Alternately, is there a different way I can utilize the MVC view engine to generate JavaScript that will set the proper Content-Type for the response?
I figured out how to meet the minimum requirements of ViewResult. One problem I was encountering was mocking the process of finding the view. This was avoidable by ensuring that the View property of my object was populated. Here is my working test:
[TestMethod]
public void TestExecuteAction()
{
var response = MockRepository.GenerateStub<HttpResponseBase>();
response.Output = new StringWriter();
var httpContext = MockRepository.GenerateMock<HttpContextBase>();
httpContext.Expect(m => m.Response).Return(response);
var routeData = new RouteData();
routeData.Values.Add("action", "FakeAction");
var context = new ControllerContext(httpContext, routeData, MockRepository.GenerateMock<ControllerBase>());
var viewResult = new JavaScriptViewResult();
viewResult.View = MockRepository.GenerateMock<IView>();
viewResult.ExecuteResult(context);
Assert.AreEqual("text/javascript", context.HttpContext.Response.ContentType);
}