ASP.NET MVC routes with "." not working in Azure - azure

I have simple route map like:
routes.MapRoute("Test", "test/{action}/{id}", new {controller = "Test", action = "Index", id = ""});
My route paths are like:
"/test/do-something/1.0.1"
Which works completely fine in local testing and self hosted .NET 4.5 on IIS7+
However, when I host it in Azure, it seems to have issues with the ID containing two ".", telling me that "The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.".
When I change the path to "/test/do-something/1" it works on Azure as well.
Why does Azure seem to prohibit ID's with "." and what can I do about it?

I would recommend using '-' in your id as opposed to '.' (periods), it's more friendly in terms of SEO.
If you really want to get it working with periods, you could use a tool called URLScan.
What is URLScan?
There is an option to configure:
AllowDotInPath=0
By default, this option is set to 0. If this option is set to 0,
URLScan rejects any request that contains multiple periods (.). This
prevents attempts to disguise requests for dangerous file name
extensions by putting a safe file name extension in the path
information or query string portion of the URL. For example, if this
option...
Here is a link to the configuration.

Related

files in server root not loading properly in Azure

I'm working on an app that instead of a database uses file system in the server's root directory. It's basically a note application that allows me to save notes. Each note is a serialized object of Note class represented by following structure \Data\Notes\MyUsername\Title.txt
When I'm testing this on localhost through IIS Express everything works fine and I can easily go step by step there.
However, once I publish the app to Azure, the folder structure is still there (made a test Controller that uses Directory.GetFiles() and .GetDirectories() to simulate folder browsing so I'm sure that the files are there) but the file simply doesn't get loaded.
Loading script that's being called:
public T Load<T>(string filePath) where T : new()
{
StreamReader reader = null;
try
{
reader = new StreamReader(filePath);
var RawDB = reader.ReadToEnd();
return JsonConvert.DeserializeObject<T>(RawDB);
}
catch
{
return default(T);
}
finally
{
if (reader != null)
reader.Dispose();
}
}
Since I can't normally debug the app on Azure I tried to dump as much info as I can through ViewData and even there, everything looks okay and the paths match, but the deserialized object is still null, and this is only when trying to open an existing note WITHOUT creating a new one first (more on that later)
Additionally, like I said, those new notes get saved in the folder structure, and there's a Note sidebar on the left that allows users to switch between notes. The note browser is nothing more but a list that's collected with a .GetFiles() of that folder.
On Azure, this works normally and if I were to delete one manually it'd be removed from the sidebar as well.
Now here's the kicker. On localhost, adding a note adds it to the sidebar and I can switch between them normally.
Adding a note on Azure makes all Views only display that new note regardless of which note I open and the new note does NOT get stored in the structure (I don't know where it ended up at all!) even though the path is defined at that point normally and it should save just like it does on localhost.
var model = new ViewNoteModel()
{
Note = Load<Note>($#"{NotePath}\{Title}.txt"), //Works on localhost, fails on Azure on many levels. Title is a URL param.
MyNotes = GetMyNotes() //works fine, reads right directory on local and Azure
};
To summarize:
Everything works fine on localhost, Important part doesn't work on Azure.
If new note is not created but an existing note is opened, Correct note gets loaded (based on URL Param) on Localhost, it breaks on Azure and loads default Note object (not null, just the default constructor data since it's required by JsonConvert)
If a new note is created, you'll see it on Localhost and you'll be able to open all other notes regardless, you will see only the new note on Azure regardless of note picked.
It's really strange and I have no idea what could cause this? I thought it had something to do with Azure requests being handled differently so maybe controller pushes the View before the model is initialized completely but that doesn't make sense since there's nothing async here.
However the fact that it loads a note that doesn't exist on the server it's even more apsurd and I have no explanation for that.
Additionally this issue is not linked with a session. I logged in through my phone and it showed the fake note there as well right away.
P.S. Before you say anything about storage, please note this. Our university grants us a very limited Azure subscription. Simple lowest tier App service and 5DTU SQL server and 99% of the rest is locked out of our subscription. This is why I'm storing stuff on the server, not because I believe it's the smart thing to do.

Azure Functions NodeJs: Remove Http Response Header

I have an HTTP triggered, NodeJs Azure Function, and I'm looking to remove the "X-Powered-By" header from my response, but have found no way to do so.
I've tried adding both this and this azure site extensions, but neither has worked for me,
Setting the response header manually, i.e. res.headers = { ['x-powered-by']: null } is ineffective.
Based on the comments made on this github issue: https://github.com/Azure/Azure-Functions/issues/290 it would seem that using either extension should have removed the headers you wanted.
Modifying the response headers will likely won't work as they are probably added further down the pipeline by the function host and not overridable, see:
Access Azure Function runtime settings
Azure functions recently removed the x-aspnet-version header, further removal of other headers is tracked as part of the azure-webjobs-script-sdk here
You should leave a comment on the github issue and you can further discuss with the team working on this.
There is an extension called Remove Custom Headers that works for Web Apps but not for functions that have their own resource group. So, what you can do is:
1. Create a regular Web App
2. Create a function and make sure you use the same Hosting Plan as the Web App (do not use Consumption).
3. Once the function is created, install the extension named: "Remove Custom Headers"
4. Restart the function and the headers (Server and X-Powered-By) should disappear.

Allow colon (:) in URL on Azure Web App

We are trying to expose a URL following the ARK standard (Archival Resource Key) from an ASP.NET website hosted on an Azure Web App. But it seems Azure Web Apps do not support colons (:) in URL path segments, as we are getting an HTTP 500 error code with message "The page cannot be displayed because an internal server error has occurred." when trying to type a URL like http://example.azurewebsites.net/ark:/123/456.
Note that we did update our web.config's RequestPathInvalidCharacters setting to allow colons in URIs, and it works locally. Also, colons in URIs may not be very frequent but are valid, even wikipedia uses them.
Edit:
Well after a few tests, it looks like the issue happens only when the colon is at the end of a path segment (e.g. : http://example.azurewebsites.net/ark:/123/456). Otherwise, the requestPathInvalidCharacters setting applies. No luck for us: the ARK standard specifies that the colon be placed at the end of a path segment.
Note that the error displayed in this case is different from the error when requestPathInvalidCharacters has its default value and a colon is placed in the middle of a path segment. Here the error seems to happen even before the request enters the IIS pipeline (maybe at the Azure level). You can test the above URL for a quick display of the problem.
Sorry for my origin reply. I try it with Azure MVC API. I configure the map route as following:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}:{id}",
defaults: new { id = RouteParameter.Optional }
);
And add the requestPathInvalidCharacters in web.config:
<httpRuntime targetFramework="4.5.2" requestPathInvalidCharacters=""/>
ValuesController:
// GET api/values/5
public string Get(int id)
{
return id.ToString();
}
After deploy to Azure I could get the result from the URL:http://.azurewebsites.net/api/values:5

Upload File with brackets ([ & ]) in the name

I'm moving a ClickOnce install from a regular web server to Azure Blob storage and have a problem with some of the files. The filenames contains [ ] and CloudBlob.UploadFile fails with an exception:
Microsoft.WindowsAzure.Storageclient.StorageException:
Error accessing blob storage: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
The code has been used for a while and only fails on files with [ ] in the name so I don't believe that it is an "authentication failure". In this particular case, this is the seventh file being uploaded in a loop. I found this link on MSDN about valid file names and this on stack overflow which both show problems with square brackets in URL's and reference UrlEncode. I added in a call to UrlEncode and that did not help. The container is created with public access since we use it to support customer downloads of our software. We have been hosting a "test" install in another container and have not had permission problems accessing that either.
I can upload the file with no name changes and then rename the file to add the "path" using newdesic's Azure Storage Explorer tool so what is that doing that I am not doing?
I see you're using the 1.7 SDK. This is a small encoding issue with the SDK which is also present in v2.0. Let's see what happens.
No encoding
account.CreateCloudBlobClient()
.GetContainerReference("temp")
.GetBlobReference("abc[]def.txt")
.UploadFile("myfile.txt");
If you don't encode the blob name, you'll end up with a request to the following URL which is causing the authentication exception:
http://account.blob.core.windows.net/temp/abc[]def.txt
The is because the SDK uses Uri.EscapeUriString internally to encode your string, but this doesn't take into account square brackets.
Encoding
Then you would expect the following to do the trick:
account.CreateCloudBlobClient()
.GetContainerReference("temp")
.GetBlobReference(HttpUtility.UrlEncode("abc[]def.txt"))
.UploadFile("myfile.txt");
The issue here is that you'll end up with this url:
http://account.blob.core.windows.net/temp/abc%255b%255ddef.txt
So what's happening here? Calling HttpUtility.UrlEncode turns abc[]def.txt to abc%5B%5Ddef.txt, which is correct. But internally, the SDK will encode this string again which results in abc%255b%255ddef.txt, which isn't what you want.
Workaround
The only way to apply encoding which takes square brackets into accounts is by using a small workaround. If you pass the full URL to the GetBlobReference method, the SDK assumes you did all the encoding yourself:
var container = account.CreateCloudBlobClient().GetContainerReference("temp");
var blob = container.GetBlobReference(String.Format("{0}/{1}",
container.Uri, System.Web.HttpUtility.UrlEncode("abc[]def.txt")));
blob.UploadFile("myfile.txt");
This results in a correctly encoded URL:
http://account.blob.core.windows.net/temp/abc%5b%5ddef.txt
And if you use a tool like CloudXplorer, you'll see the blob with the correct filename:
There are two known breaks in the Uri class in .Net 4.5
• ‘[‘,’]’ characters are no longer escaped
• ‘\’ character is now escaped as %5C
This is causing an authentication when the server attempts to validate the signature of the request as the canonicalized string is now different on the client and the server.
There are a few workarounds clients can use while this issue is present. The correct solution will depend on your specific application and requirements.
Avoid the ‘[‘,’]’, or ‘\’ characters in resource names
By simply avoiding these characters all together you will be able to avoid the issue described above.
Target .Net 4.0
Currently the recommendation is for clients to simply continue to target their applications to .Net 4.0 while a full solution is being investigated. Note, since .Net 4.5 is an in place upgrade clients can still take advantage of some performance improvements in the GC etc, without specifically targeting the .Net 4.5 profile. For Windows RT developers this is not an option and you will therefore require the workarounds detailed below.
Pre-Escape Data
If possible a client can pre- escape the data or replace the given characters with non-affected ones.
This is why the workaround above is working.

Serving .config files

We have a legacy (classic asp) CRM that I maintain in my organization. Users may upload files through the web front, they are stored on a network share and the filename, uploader, etc is saved to a database. Everything is well and good with the exception of .config files.
For some reason certain people can download these just fine, but other people recieve this error:
The type of page you have requested is not served because it has been explicitly forbidden. The extension '.config' may be incorrect.
it would seem that on some users computers the link for the file is "file://networkshare/filename" (which works) and on other machines it is "http://networkshare/filename". (which doesn't work)
I have the mime type for .config set to text/plain in iss6. All users are running IE8.
The code on the page creates a href links based on records returned from the database.
Why then is there there the difference in the way the link is rendered differently in the same browser on different pc's? How do I allow .config files allowing people to view the sites web.config?
The code that builds the link is:
function getlink(file_nm,path)
{
thisPage.navigate.CheckDocumentAttachedToRequest(file_nm, path)
var sDocLink = path.replace(/\//g,"\\") + "\\" + file_nm;
return "<A class=\"parislink2\" TARGET=\"_BLANK\" HREF=\"\\\\" + thisPage.get_sServerName() + "\\" + sDocLink + "\">" + file_nm + "</A>";
}
Weird.
I know that IIS 6 will return error 404.3 if a client request refers to a file name extension that is not defined in the MIME types.
However you do have it defined. You can try as a test using the wildcard () in your mime types. ( for the file extension and text/plain for the mime type.) The wildcard can be a security risk but if you are serving up configs..perhaps this application and server are internal to your network and it would be ok to use the wildcard.
I would also check your ISAPI extensions (not filters, but extensions) and make sure .config
is still in there. It should be by default.
Defining a mime type at the global level in IIS should filter down through and override any mime types set at the folder level.
An IIS reset is needed everytime you change mime types.
Perhaps it is a browser issue?
(an issue on the client side for the links that do not work..an issue like "browser control".)
It is almost as if some of the browsers are interpreting your function correctly when the link is built..and others are substituting "http" instead of "file" as the protocol when they render the HTML from the function call. Perhaps you could hardcode your function to us "file:" as a string that is placed at the begining of your link code. (trying to overide any "http" string that gets place in there by the HTML sent back by the server or rendered by IE8.)
The wildcard was filtered out for security purposes in the above post. (wildcard = "an asterisk")

Resources