IIS 7.5 405 Method Not Allowed for PUT from StaticFileModule - c#

I'm integrating a 3rd party xml editor into our web app and the save function performs an HTTP PUT directly to the file on the web server.
The OS is Windows Server 2008 R2 using IIS 7.5
We have a Web API installed so we already have WebDAV removed and also have updated the web.config with:
<remove name="WebDAVModule" /> under modules
<remove name="WebDAV" /> under handlers
We've updated the Handler Mappings of the site to include the 'PUT' verb:
StaticFile
ExtensionlessUrlHandler-ISAPI-4.0_32bit
ExtensionlessUrlHandler-ISAPI-4.0_64bit
We still continue to get the following response in fiddler when we make a PUT request to an xml file in the Composer:
HTTP Error 405.0 - Method Not Allowed
The page you are looking for cannot be displayed because an invalid method (HTTP verb) is being used.
Module : StaticFileModule
Notification : ExecuteRequestHandler
Handler : StaticFile
Error Code : 0x80070001

When you installed your aplication in IIS in Module:
Find WebDav and remove the same step you must do in Handler Mappings - remove WebDav and refresh all.

Add PUT, DELETE verbs to PHP.cgi request restrictions.
IIS -> Sites -> DOMAIN.COM -> Handler Mappings -> Edit the CGI handler handling your requests -> Request Restrictions -> Verbs tab.

Related

ASP.Net Core Web API, deployed under IIS is returning 404

I have a new Web API developed in ASP.NET Core. This Web API is supposed to be deployed in IIS and will have to work over SSL, so I have the [HttpsRequired] attribute on all my controllers. I struggle to make it work while deployed, so for now I relaxed the requirements and commented out those attributes. Doing so, I was able to create two bindings in IIS, one for HTTPS and one for HTTP. Given that my Web API is created in ASP.NET Core, I followed the deployment steps Rick Strahl has in his excellent blog post. I have selected "No Managed Code" for the .NET CLR version. The IIS machine is a 64-bit Windows Server 2012 R2 environment - not sure whether this matters or not. The .NET Core Windows Server Hosting bundle has been installed on the server and I can see the AspNetCoreModule listed in the Modules grid.
If i try to access the Web Api (I created a very simple GET method that returns some information regarding the assembly) with Fiddler, I get a 404 error. For now, i run Fiddler on the same machine, so I tried all combinations (localhost, IP address and full machine name in the domain).
No errors are logged in the EventViewer. Does anyone have any suggestion on how to troubleshoot this issue?
TIA,
Eddie
EDIT1: Here is my controller:
[Route("api/info")]
//[RequireHttps]
public class InfoController : Controller
{
private ITncRepository _repository;
public static ApplicationAssemblyDetails ApplicationAssemblyDetails { get; set; }
public InfoController(ITncRepository repository)
{
_repository = repository;
ApplicationAssemblyDetails = ApplicationAssemblyDetails.Current;
}
[HttpGet("")]
public JsonResult Get()
{
return Json(new WebApiInfoModel()
{
CurrentTime = DateTime.Now,
CurrentUtcTime = DateTime.UtcNow,
AssemblyName = ApplicationAssemblyDetails.ApplicationAssembly.FullName,
VersionNumber = ApplicationAssemblyDetails.VersionNumber,
BinFolder = ApplicationAssemblyDetails.BinFolder,
BuildMode = ApplicationAssemblyDetails.BuildMode,
TradeMark = #" © 2016-2017 * SomeCompany (www.somecompany.com)"
});
}
}
The ApplicationAssemblyDetails is a nuget package that gives some info about the current assembly. WebApiInfoModel is my model class for the Web API Information I want to pass back as a test to the client.
The web.config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath=".\My_ASP_NET_Core_Web_API.exe" arguments="" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="true" />
</system.webServer>
</configuration>
Finally, to answer your last question, Ignas, I use a Publishing Profile that uses the File system as a method, targets the .NET Framework 4.5.2, using the release configuration. Given that my project is a Web API and not an MVC 6 Web Application, the publishing package creates a stand-alone application. Since the clients need to call my Web API using SSL, I think that it has to be hosted in IIS, so running the standalone application would not work. Of course, for testing purposes, I could try to run it. That's why I commented out the [HttpsRequired] attribute. I will try that and report back, but for now I hope I gave you all the information you required.
I'm having a setup very close to yours (Asp.Net core, Web API, IIS, HTTPS ...) working fine on my end.
I faced the same issue at some point because I was not using the proper path to access my controller/action, it depends on how you deployed it under IIS. For instance, in my case when I use Kestrel directly it goes through a URL like that:
http:// localhost:5000/controllerName/actionName
But I can also contact my Web API via IIS and in that case I need to use a URL like that:
http:// localhost:5001/applicationName/controllerName/actionName
Have you created an application under IIS that could explain you getting a 404 because you would not use the proper path?
For instance, in my case:
screenshot of the asp.net core api under iis
And I'm accessing it, through the URL:
https: //servername:serverport/RequestPortalAPI/ControllerName/ActionName
In the end, it was a matter of properly configuring Widows Authentication. For Fredrik and anyone else reading this post for a solution, these are the steps I performed:
In IIS, in the Authentication form for my Web API, I disabled Anonymous Authentication and I enabled Windows Authentication:
Make sure that "Negotiate" is at the top of the list for Enabled Providers:
In the Application Pools, I configured my Web API to run under an account that the UIT department of my client has given me:
The configuration file of my Web API (web.config) contains the following settings:
Now we are getting into the dark areas of the problem. In order to use Windows Authentication and let the credentials of the caller be passed through to the backend (in my case a SQL Server database), the Web API has to be configured to use Kerberos. I found this after I opened a ticket with Microsoft and I worked closely with one of their engineers. For this to happen, you need to follow these steps:
Create a Service Principal Name (SPN) for your Web API and the domain account it runs under. You need to run this command:
Where hostname is the fully qualified domain name of your Web API. The Domain\Username are the domain account under which the Web API is running. You need special domain privileges, so you may want to involve someone from IT. Also, from now on, you need to access your Web API by the full domain name, not by IP address. IP address won't work with Kerberos.
Also, with the help of your IT person, you need to enable delegation for any service using Kerberos for the domain account under which you run your Web API. In the Active Directory Users and Computers, locate the account you use to run your Web API, bring up its properties, click on the Delegation tab and enable the second option "Trust this user for delegation to any service (Kerberos Only):
We have also made some changes on the server that runs our database, but I am not 100% those are truly required, so I won't add them here because I don't even know if you use SQL Server or some other backend repository.
Let me know if you need those as well and I will add them later.
Good luck,
Eddie

HttpClient basic authentication against Web API fails, while browser works as expected

I'm testing my own Web API service, and after adding of
[Authorize(Roles = "MyRole")]
to the controller, all requests made by HttpClient fails with "Unauthorized" (401). Service is hosted in IIS Express with Windows authentication enabled, as suggested here.
Client sends appropriate request header:
var authHeaderParameter = Convert.ToBase64String(Encoding.ASCII.GetBytes("MyUser:MyPassword"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authHeaderParameter);
The same request (at least, the same URI and credentials) made from browser works as expected and returns data.
Fiddler shows, that browser sends "Proxy-Authorization" request header, and doesn't send any "Authorization".
What am I doing wrong?
How to fix request using HttpClient?
UPD.
This doesn't help too:
var handler = new HttpClientHandler
{
UseProxy = false
};
var client = new HttpClient(handler, true)
{
BaseAddress = new Uri(baseAddress)
};
Well, the problem was located inside IIS Express settings.
I'll post this answer and shall add "VS 2015" tag into question, because it might be helpful.
Thanks to #swiley, WireShark and npcap (the last is needed to capture loopback interface traffic via WireShark).
Inspecting response headers, that were sent to web browser, I've found, that 401 responses contain Autorization: NTLM headers. Since browser automatically handles this case, it sends current NTLM credentials in further requests and get the requested data. My HttpClient code does not, and, actually, must not handle NTLM.
Prerequisites.
First of all, this is VS 2015 and my Web API project uses IIS Express for hosting, which is the default setting. Non-default here is that I've changed port to the constant value:
The second, IIS express in VS 2015 stores its configuration in %SolutionDir%\.vs\config\applicationhost.config file. Note, that this was changed from previous versions.
The third.
Project properties, available on F4 key press, are very limited, and, in fact, you're just modifying the same applicationhost.config from above:
The fourth, this post doesn't helps:
To enable Basic authentication using IIS, set the authentication mode
to "Windows" in the Web.config of your ASP.NET project:
While this will work with "mature" IIS, Visual Studio + IIS express just ignore these settings.
The solution.
Open %SolutionDir%\.vs\config\applicationhost.config in text editor.
Find first <authentication> tag.
Under it, find <basicAuthentication enabled="false" />, and change enabled to true.
Save file.
Restart Web application.
Note, that properties you can see by pressing F4 are stored under <location path="YourProjectName"> tag.
By default, it has sub-tag authentication, but without basicAuthentication:
<authentication>
<windowsAuthentication enabled="false" />
<anonymousAuthentication enabled="false" />
</authentication>
If solution has more that one IIS Express-hosted project with custom authentication settings, one should add basicAuthentication into project-related section instead of first <authentication> tag, which is global config per solution.
I would post a comment but my reputation is too low, in the past I've had this problem when the server sent back an http redirect and the http library automatically sent back my request without the custom header data. I think the request or response object will have a uri field if this happens, you can also disable automatic redirection handling. I ended up figuring all this out using wire shark though and I highly suggest you do that next.

IIS7 URL Rewrite returns 404 for WCF requests (reverse proxy)

I am using IIS7.5, .net 4.0. I am working locally.
I have installed Application Request Routing, Web Farm Framework, WebDeploy and UrlRewrite to set up a reverse proxy. This works fine for the most part.
I have two websites:
DefaultWebSite (port 80, app pool: Default App Pool (.net 4)) and
Target (port 8085, app pool: TargetAppPool(my identity, .net 4)).
I have a rewrite rule on DefaultWebSite (created as directed on IIS.net) which redirects all localhost (port 80) traffic to localhost:8085 just as detailed in the above link. This works fine for most document types (.aspx, .xap, .htm, .ico) but a request to MyService.svc fails. It returns a 404.
To be clear:
When I paste localhost:8085/MyService.svc into a browser I get the requested WCF page.
When I paste localhost/MyService.svc into a browser I get a 404.
When I paste localhost:8085/MyIcon.ico into a browser I get the requested resource.
When I paste localhost/MyIcon.ico into a browser I get the requested resource.
.svc is the only document type that I've found that returns a 404.
I've got two pieces of info that might be of relevance.
App Pools. When I change the DefaultWebSite's app pool to TargetAppPool then the 404 becomes a 500 ("Failed to map the path '/'"). All other requests are successful when this change is made. Not sure if this relevant or not.
FREB (Failed Request Tracing) Log. I found a page (http://blogs.msdn.com/b/asiatech/archive/2011/08/25/return-404-4-not-found-when-url-rewrite.aspx) which details the steps in a FREB log when a URL rewrite is more successful than mine (it fails later on). I've not been able to find out how to generate a FREB log for a successful rewrite (if that's possible) so I can only compare my FREB log to the one on that blog. I can see that their step 21 (URL_CHANGED) in my FREB log but not 22 (URL_REWRITE_END). I've not got enough experience with these logs to notice anything more significant than that (suggestions welcomed).
My main question is: does anyone know why just URLs requesting .svc resources are not being rewritten?
A secondary question is: does anyone know how to generate a FREB log for successful request (if it's even possible)?
Thanks
Update:
I have changed the architecture to try to get more info.
I have moved the Target website to a different PC on which I have installed Microsoft Network Monitor to capture the incoming traffic.
Before I changed the url-rewrite rule to point at this new website I got the correct response when I made a request to MyService.svc on the new PC. Fine.
As soon as I changed the rewrite rule to route the request to the new Target website then it responds as before (404). I have made both POST and GET requests. There is no sign of any of the requests in the Network Monitor log (all other calls -200, 404 or otherwise- appear in this log).
This leads me to think that there is something incompatible with url-rewrites and *.svc requests. I tried making a request to MyService.asmx (having created this file) and it correctly returned a page, so it is limited to *.svc. Any ideas?
The solution to this is in the config file of the Target web site.
In web.config (in the Target application) there is a section which read:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>.
I changed this to read:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />.
Credit must go to http://forums.iis.net/post/1956671.aspx for this (although s/he claims it is the proxy's config which needs to be changed, but I found it be the Target app, not the proxy server).
If you still can't get it running, make sure you don't have the WCF handlers on the website which acts as the reverse proxy.
I disabled this by adding this web.config of the reverse proxy:
<system.webServer>
...
<handlers>
<remove name="svc-ISAPI-4.0_64bit" />
<remove name="svc-ISAPI-4.0_32bit" />
<remove name="svc-Integrated-4.0" />
</handlers>
</system.webServer>
Because the rewrite appears to work for all resources except when the extension is .svc I would say this would be the area to concentrate on.
I would imagine that the rewrite rules are matching your other resources, but not your service, and because these are usually regular expressions (which are often complicated) I would say it would be worth testing any rules you find with your urls. Details of how to find the regular expressions for an UrlRewrite can be found here.
It is also probably also worth looking at any outbound rules with the same mindset.

Google+ signin "Getting Started" project - problems with IIS

Using the C#/.NET Google+ sign-in quick start project, I'm hitting problems with IIS6. Here are the steps I followed:
downloaded the project from Github
modified the index.html and signin.ashx files to contain my Client ID and Client Secret
running the project on my machine (using the built in web server for Visual Studio 2010) works fine
published to Windows 2003 server with IIS6
added "index.html" as a default document for the web site
set the web site to use an app pool configured for the 4.0 .NET framework
attempted to access the page from Chrome
Accessing the site with no page specified on the URL (https://myserver.com/gplussample/) brings up the Google+ signin button. This works great and I'm taken to the page with my profile photo, circles, etc.
However, when I click the "disconnect" button, nothing happens. Using Chrome DevTools to examine the process, I see this error:
POST https://myserver.com/gplussample//disconnect 404 (Not Found)
The problem is the //disconnect - there's no page name (I believe it should be signin.ashx, as that's what works when I'm running the app on the dev web server with Visual Studio 2010).
I then attempted to access the site with a page name specified:
https://myserver.com/gplussample/signin.ashx
That results in a blank page and again, looking at the Chrome DevTools, I see a 400 Bad Request error for the .ashx handler. I searched and searched for solutions for .ashx handlers and "bad request" errors, with no success in this particular case.
Thinking IIS6 was the culprit, I published the site to an IIS7 instance.
With no page name specified on the URL (http://localhost/gplusoriginal/), I encountered the same error with the "disconnect" button - no action and a 404 error.
When I changed the URL to http://localhost/gplusoriginal/signin.ashx, I received this error:
Could not create type 'GPlus_ServerSideFlow.Signin'.
Again, back to Google and checking on .ashx handlers and issues with IIS7. I found a post about the web.config and specifying the handler there, so I tried that.
<system.webServer>
<handlers>
<add name="GPlus_ServerSideFlow.Signin" path="*.ashx" verb="*"
type="GPlus_ServerSideFlow.Signin" resourceType="Unspecified" />
</handlers>
</system.webServer>
Adding this snippet to the web.config resolved the "could not create type" error, but resulted in another 400 Bad Request error.
So, my questions are: What has to be done with II6 or IIS7 to get this sample project working? Are there additional steps in configuring IIS that need to be completed? Or something missing from the project code?
Thank you
The way that the sample works is that the RESTful endpoints are intercepted by an ashx handler, signin.ashx.cs. The handler can't be directly addressed so routes are setup in global.ashx.cs to map endpoints (/, /connect, /disconnect, etc) to that route handler.
As the sample ships, it assumes the built-in web server running on the root port. When moving to IIS, you need to change the path matchers from Equals to EndsWith in order to match the virtual directory you are deploying to:
// Redirect base path to signin.
if (context.Request.Path.EndsWith("/"))
{
context.Response.RedirectPermanent("signin.ashx");
}
// This is reached when the root document is passed. Return HTML
// using index.html as a template.
if (context.Request.Path.EndsWith("/signin.ashx"))
{
Apologies for the delay on this... but hopefully that fixes it! This fork of the C# starter has the changes in it, tested with IIS, and this update may end up getting merged back into the official sample soon.

Validation of viewstate MAC failed -View State Error

In my website, when a web page is idle for more than 5 minutes, then that page is not working until I refresh. The following error occurs:
Error:
Sys.WebForms.PageRequestManagerServerErrorException:
Validation of viewstate MAC failed. If
this application is hosted by a Web
Farm or cluster, ensure that
configuration specifies
the same validationKey and validation
algorithm. AutoGenerate cannot be used
in a cluster.
I'm already using EnableEventValidation="false" ViewStateEncryptionMode="Never" ValidateRequest="false"
But, nothing is working for me.
Although it's an old question, I will answer anyway because it might help someone else.
So I had this problem in the past few days, and I realized that I started getting this error after I configured my cookies as HttpOnly and Require SSL:
</system.web>
<httpCookies httpOnlyCookies="true" requireSSL="true" />
</system.web>
Turns out that I just forgot to configure Visual Studio to open the SSL URL of my website. So as long as it opened the regular Url, the cookies couldn't be sent, and that what caused the error.
In order to change the default Url, you simply need to figure out what is your SSL url: Click the project on solution explorer and press F4 (not Right Click -> Properties) and over there you'll see SLL URL under the the Development Server section. After that, go to the project properties page (Right Click -> Properties) and in the Web tab, put the SSL Url as the Project Url.
Make sure all the servers on the cluster are using the same encryption key.
This sometimes happens if you are doing a postback from a form which has an action pointing to a different page.

Categories