I am trying to use a controller as an image handler, but how do i pass in a path to it?
Right now it looks like this (works for images without a path):
public void GetImage(string parameter)
{
var imageHandler = UnityGlobalContainer.Container.Resolve<IImageHandler>();
imageHandler.ProcessRequest(parameter);
}
But if i try to send in the path folder1\folder2\folder3\picture.jpg then it fails.
#Html.ActionLink("Show", "GetImage", "Utility", new { parameter = #"folder1\folder2\folder3\picture.jpg" }, new { })
produces this:
http://localhost:58359/Utility/GetImage/folder1%5Cfolder2%5Cfolder3%5Cpicture.jpg
and that leads to:
HTTP Error 400 - Bad Request.
How can i pass in a path to the controller using the normal mvc approach?
(I am using backward slashes and not forward slashes)
I have also tested using HttpUtility.UrlEncode on the parameter.
According to your code: The produced link in the html page should be:
http://localhost:58359/Utility/GetImage?parameter=folder1%5Cfolder2%5Cfolder3%5Cpicture.jpg
and the parameter variable should be correctly set to "folder1\folder2\folder3\picture.jpg" in the action method.
Notice that you might be vulnerable to directory traversal here.
In .NET 4.0 beta 2, the CLR team has offered a workaround.
Add this to your web.config file:
<uri>
<schemeSettings>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
This causes the Uri class to behave according to the RFC describing URIs, allowing for slashes to be escaped in the path without being unescaped. The CLR team reports they deviate from the spec for security reasons, and setting this in your .config file basically makes you take ownership of the additional security considerations involved in not unescaping the slashes.
Can you not just decode the parameter?
http://msdn.microsoft.com/en-us/library/6196h3wt.aspx
Instead of calling the filename parameter 'parameter', and defining it in your route, call it 'filename' and DON'T define it in your route.
Your action code will be the same, but the filename will stop being part of the route and just be an ordinary URL parameter.
If you're afflicted by this season's fashion for disliking URL parameters, then you might find this repugnant, but that's just fashion and can safely be ignored.
Personally, I wouldn't pass paths like this into a web app, because I would be absolutely paranoid about creating traversal threats by mistake - I only ever pass in path-free filenames, validate them against a list and then fetch the file.
Related
I have my rest client url hard-coded in my code-behind, but upon peer-reviewing my code, I was asked to move that url to the config file so that it can be changed for each environment.
Visual Studio 2019 now complains because my rest client url has an invalid = sign as token in the url itself, and it expects ; as token instead.
Has anyone ever come across this, and is it correct to move the rest client to the config file? In theory that should not change.
Can't share the full url, but the part that is highlighted as error is this: version=2.0&details=true.
I found the answer. The problem is in the & symbol itself. Once converted to &, the errors Visual Studio was highlighting were gone and my solution worked again.
If i will do that i will save in config file only base url like this
"WebConfig": {
"SmsCenterApi": "https://some_site.com/SendService"
}
and in code I can complete the link
string url = WebConficData.SmsCenterApi+"version=2.0&details=true";
andafter that I can use url to make some request. For multi-environments web.config and appsettings is avesome. You just change base url for each env and that's it.
I think the answer to your questions
where do you store the rest client url?
is it correct to move the rest url to the config file?
is dependent on how you implement the rest request to that url. As you do not show any information on how you implement the rest call, I would like to show you one possible way and hopefully give you an impression about which things you should consider when implementing a solution.
So we can basically (for the sake of completeness) split an rest-endpoint url into two parts which might affect our implementation.
The base url:
"https://www.some-nice-name.com/SomeEndPoint"
and the parameters
?key1=value1&key2=value2
having this in mind, you could go the way and split them up, storing the base url and the parameters in two different nodes/attributes in a config file:
{
"BaseUrl" : "https://www.some-nice-name.com/SomeEndPoint",
"UrlParams" : "?key1=value1&key2=value2"
}
Or in one node/attribute, or even split each single parameter pair ("key1=value1") into own fields. And so on, and so on......
Anyway, if we now jump into our C# code and implement the Rest call, we have a wide range of different possible solution. For this example I will show you how to use the RestSharp NuGet package and why it might influences our decision on the above question.
So one basic example:
// I will not show the implementation of ReadYourConfigStuff() because its fairly clear what should happen here
var config = ReadYourConfigStuff();
// Give the BaseUrl to our REST client
var restClient = new RestClient(config.BaseUrl);
// Just taking GET as we have some GET Parameters
var restRequest = new RestRequest(Method.GET);
so far so good. But we still miss our parameters right?
Let's go ahead:
// RestSharp gives us a very nice tool to add GET parameters to our request
restRequest.AddParameter("key1", "value1");
restRequest.AddParameter("key2", "value2");
That looks quite different to what we added to our config file, does it? Yes it does. As RestSharp gives us a tool at hand which allows to add parameters one by one, we are free to choose how to store and maintain those in our code. And if we have a look on the AddParameter defintion
public IRestRequest AddParameter(string name, object value);
we see that the second parameter can be any object. Amazing!
So my answer to your question is: Yes you can store it in the config file, but does it fit to your implementation? Are the parameters fix or do they change? How does your favorite tooling would like you to implement the rest request?
Based on the answers to these questions, I would take a decision rather to use a config file or not.
I'm using ASP .NET MVC Beta and I get the HTTP 404 (The resource cannot be found) error when I use this url which has a "dot" at the end:
http://localhost:81/Title/Edit/Code1.
If I remove the dot at the end or the dot is somewhere in the middle I don't get the error.
I tried to debug but it I get the error from "System.Web.CachedPathData.GetConfigPathData(String configPath)" before ProcessRequest in MvcHandler.
Is "dot" not allowed at the end of a url? Or is there a way to fix the route definition to handle this url?
For an example: I have a table named Detail1 [Id(integer), Code(string), Description(string)] which has FK relationship with Master1 through it's Id column. Whenever I select a record of Master1, I also select it's Detail1 record to get it's Code field. In order to not to make this join everytime (since usually there isn't only one detail, there are more than one) I choose not to use Id column and I make Code PK of Detail1.
But when I get rid of Id and use Code as PK then my routes also start to work with Code field, like: Detail1\Edit\Code1
This Code can have anything in it or at the end, including DOT. There are cases where I can prohibit a DOT at the end but sometimes it's really meaningfull.
And I'have also seen this post that routes can be very flexible, so I didn't think mine is so weird.
So that's why I do something so non-standard. Any suggestions?
And also why it's so weird to have a DOT at the end of a url?
If you are using .NET 4.0, you can set this flag in the system.web section of your web.config and it will be allowed:
<httpRuntime relaxedUrlToFileSystemMapping="true" />
I've tested it and it works. Haack has an explanation of it.
This can be solved in a couple of ways in every ASP.NET version from 1.0 and up. I know it's two years after this thread has been created, but anyway, here it goes:
Cause
Creating your custom error handler, or configuring a custom page in IIS for redirecting the 404 will not work. The reason is that ASP.NET considers this URL dangerous. Internally in System.Web.Util.FileUtil, ASP.NET calls a private method IsSuspiciousPhysicalPath, which tries to map the path to a (virtual but legal) filename.
When the resulting legalized path is not equal to the original path, processing stops and the ASP.NET code returns a 404 (it doesn't ask IIS or the web.config for the custom 404, it returns one itself, which makes it so hard to do something about this).
Windows Explorer works the same way. Try to create a filename ending in one or more dots, i.e. test.txt.. You will find that the resulting name is text.txt.
Solution for ending URL in a dot in ASP.NET
The solution is simple (once you know it, it always is). Just before it sends out this 404, it will call Application_PreSendRequestHeaders, a simple event that you can register to in Global.asax.cs (or the VB equivalent). The following code will return a simple text to the browser, but a Redirect, or any other valid response is also possible.
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
HttpResponse response = this.Context.Response;
HttpRequest request = this.Context.Request;
if (request.RawUrl.EndsWith("."))
{
response.ClearContent();
response.StatusCode = 200;
response.StatusDescription = "OK";
response.SuppressContent = false;
response.ContentType = "text/plain";
response.Write("You have dot at the end of the url, this is allowed, but not by ASP.NET, but I caught you!");
response.End();
}
}
Note: this code also works when "aspx" is not part of the URL. I.e., http://example.com/app/somepath. will call that event. Also note that some paths still won't work (ending with multiple dots, with a hash-tag, or a < -sign, for instance, causes a 400- Bad Request). Then again, it does work for ending on a quote, a space+slash, or multiple dots separated by spaces.
Well, in .NET 4.5 I fixed this problem by adding "/" to the end of the url.
So, in your case it would be "http://localhost:81/Title/Edit/Code1./". It was the only thing I did, I didn't have to add httpRuntime setting.
add this to handlers
<add name="ExtensionlessUrlHandler-Integrated-4.0-ForApi"
path="api/*"
verb="*"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
Perhaps http://localhost:81/Title/Edit/Code1%2E would work.
I escaped the period with a hex ascii code.
Why can't you have a dot-terminated URI?
Because a URI is a resource request and a historical imperitive exists on all relevant operating systems that the dot character is the extension separator. The last dot is treated as denoting a file extension, hence dot-terminating will make no sense.
Also worth reading:
RFC1738
RFC3986
I'm trying to apply an IgnoreRoute to a path that contains "Rejected-By-UrlScan", and don't understand the syntax. The MSDN documentation here provides no examples.
https://msdn.microsoft.com/en-us/library/system.web.mvc.routecollectionextensions.ignoreroute(v=vs.118).aspx
Here is an example path that I'm dealing with:
http://example.com/Rejected-By-UrlScan?~/Content/fonts/glyphicons-halflings-regular.woff2
These are some IgnoreRoute examples that I've picked up, but all of these are directly related to file extensions. In this case I'm not trying to isolate a file extension, but to simply ignore requests that contain "Rejected-By-UrlScan" in the path.
routes.IgnoreRoute("{*allaspx}", new { allaspx = #".*\.aspx(/.*)?" });
routes.IgnoreRoute("{*favicon}", new { favicon = #"(.*/)?favicon.ico(/.*)?" });
routes.IgnoreRoute("{*robotstxt}", new { robotstxt = #"(.*/)?robots.txt(/.*)?" });
The site that I'm working on logs exceptions. Presently when the Rejected-By-UrlScan path appears, this is the exception that gets logged:
System.Web.HttpException: The controller for path '/Rejected-By-UrlScan' was not found or does not implement IController.
Now, I can extend the Application_Error event in Global.asax to ignore exceptions that contain the text "Rejected-By-UrlScan". But I would prefer to not even throw the exception in the first place by simply adding the rule.
What is the correct syntax to ignore a route that contains "Rejected-By-UrlScan"? If you can provide the answer and point me to some documentation that explains the syntax with examples, I would be grateful. Thank you.
My question to you is after you ignore it what do you want to do. The reason we ignore static file paths is to avoid the route module from processing static files such as favicon.ico and instead a normal asp.net request process will proceed. The following code will ignore it but the normal asp.net request will result in 404.
routes.IgnoreRoute("{reject}", new { reject = #"(.*/)?Rejected-By-UrlScan(/.)?" })
all. I am trying to document a WebApi 2 using Swashbuckle package.
All works great if the API is running by itself i.e. localhost/api/swagger brings me to ui and localhost/api/swagger/docs/v1 to json.
However the producation app initializes this same Webapi project by running webapiconfig method of this project from global.asax.cs in another - now web project (the main application one). So the api url looks like localhost/web/api instead of localhost/api.
Now swashbuckle doesn't work like that at all.
localhost/api/swagger generates error cannot load
'API.WebApiApplication', well of course
localhost/web/swagger = 404
localhost/web/api/swagger = 404
I tried to look everywhere, but all I found is workaround.
c.RootUrl(req => req.RequestUri.GetLeftPart(UriPartial.Authority) + VirtualPathUtility.ToAbsolute("~/").TrimEnd('/'));
Unfortunately it doesn't work, now maybe it should and I just need to change something but I don't even know what exactly this property expects and what it should be set to.
May be it's not even applicable - maybe setup we have requires something else or some swashbuckle code changes.
I will appreciate any help you can provide. I really starting to like swagger (and swashbuckle) for rest documentation.
For Swashbuckle 5.x:
This appears to be set by an extension method of httpConfiguration called EnableSwagger. Swashbuckle 5.x migration readme notes that this replaces SwaggerSpecConfig. SwaggerDocConfig RootUrl() specifically replaces ResolveBasePathUsing() from 4.x.
This practically works the same as it did before, looks like the biggest change was that it was renamed and moved into SwaggerDocConfig:
public void RootUrl(Func<HttpRequestMessage, string> rootUrlResolver)
An example from the readme, tweaked for brevity:
string myCustomBasePath = #"http://mycustombasepath.com";
httpConfiguration
.EnableSwagger(c =>
{
c.RootUrl(req => myCustomBasePath);
// The rest of your additional metadata goes here
});
For Swashbuckle 4.x:
Use SwaggerSpecConfig ResolveBasePathUsing and have your lambda read your known endpoint.
ResolveBasePathUsing:
public SwaggerSpecConfig ResolveBasePathUsing(Func<HttpRequestMessage, string> basePathResolver);
My API is behind a load balancer and this was a helpful workaround to providing a base address. Here's a dumb example to use ResolveBasePathUsing to resolve the path with a known base path.
string myCustomBasePath = #"http://mycustombasepath.com";
SwaggerSpecConfig.Customize(c =>
{
c.ResolveBasePathUsing((req) => myCustomBasePath);
}
I hardcoded the endpoint for clarity, but you can define it anywhere. You can even use the request object to attempt to cleanup your request uri to point to /web/api instead of /api.
The developer commented on this workaround on GitHub last year:
The lambda takes the current HttpRequest (i.e. the request for a given
Swagger ApiDeclaration) and should return a string to be used as the
baseUrl for your Api. For load-balanced apps, this should return the load-balancer path.
The default implementation is as follows:
(req) => req.RequestUri.GetLeftPart(UriPartial.Authority) + req.GetConfiguration().VirtualPathRoot.TrimEnd('/');
...
Re relative paths, the Swagger spec requires absolute paths because
the URL at which the Swagger is being served need not be the URL of
the actual API.
...
The lambda is passed a HttpRequestMessage instance ... you should be able to use this to get at the RequestUri etc. Another option, you could just place the host name in your web.config and have the lambda just read it from there.
I need to change the URL on my address bar.
I looked for URL Rewrite but as far as I've seen it works for a request like this:
url.com/mypage.aspx?xp=asd&yp=okasd
and transforms that into:
url.com/mypage/asd/okasd
http://www.iis.net/downloads/microsoft/url-rewrite
That's not my scope. I already have MVC Routes working with url.com/mypage. The problem is that when I type that URL I am redirected (that's the behavior I want) to url.com/otherpage/actionX?param=value. The problem is that I still want the address bar to show url.com/mypage. Will URL Rewrite work for that?
I am asking because I don't know if it will work since it's an internal redirect (RedirectToAction) instead of a 'regular' access.
In case someone wonders why I can't make a route for that, as explained in my question I alread have one rule for that url.com/mypage that redirects to a 'router' which decides what action to call.
I've seen some questions, but I don't think they cover my specific problem:
MVC3 change the url
C# - How to Rewrite a URL in MVC3
UPDATE
This is my route:
routes.MapRoute(
"Profile", // Route name
"{urlParam}", // URL with parameters
new { controller = "Profile", action = "Router" } // Parameter defaults
);
Inside Router action I redirect to the correct action according to some validation done on urlParam. I need this behavior since each action returns a different View.
Updated my tags since I am now using MVC4
Thanks.
I once had to run a php site on a windows box. On the linux box it originally ran, it had a rewrite defined to make site process all request in only one php file (index.php).
I've installed and configured URL Rewrite with following parameters
Name : all to index.php
Match URL ------------------------------
Requested URL : Matches the Pattern
Using : Regular Expressions
Pattern : (.*)
Ignore Case : Checked
Conditions -----------------------------
Logical Grouping : Match All
Input : {REQUEST_FILENAME}
Type : Is Not a File
Action ---------------------------------
Action Type : Rewrite
Action Properties:
Rewrite Url : /index.php?$1
Append Query String : Checked
Log Rewritten URL : Checked
this makes all requests to site (except files like css and js files) to be processed by index.php
so url.com/user/1 is processed on server side as url.com/index.php?/user/1
since it works on server side client url stays same.
using this as you base you can build a rewrite (not a redirect).
Server.Transfer is exactly what you need, but that is not available on MVC.
On the MVC world you can use the TransferResult class defined in this thread.
With that... you add code to your ROUTE action that process the urlParam as always and instead of "redirecting" (RedirectToAction) the user to a new URL, you just "transfer" him/her to a new action method without changing the URL.
But there it a catch (I think, I have not tested it)... if that new page postbacks something... it will NOT use your router's action URL (url.com/mypage), but the real ACTION (url.com/otherpage)
Hope it helps.
In my opinion,you can try following things:
Return EmptyResult or RedirectResult from your Action method.
Also,you need to setup and construct outbound route for URL that you required.
Secondly, if these didn't work,the crude way to handle this situation is with Div tag and replacing the contents of Div with whatever HTML emitted by Action method. I am assuming here that in your problem context, you can call up jquery ajax call.
Hope this Helps.
The problem you have is that you redirect the user ( using 302 http code) to a new location, so browser ,reloads the page. you need to modify the routes to point directly to your controller. The route registration should be routes.MapRoute("specific", "my page", new { controller = "otherpage", action="actions", param="value"}).
This route should be registered first