Acess denied / Method Not allowed - some browsers only - ajax

I have created a WCF service, and am communicating with it using ajax/json 'get' commands. It's working fine on Edge, Chrome (Windows desktop), Firefox (Windows desktop). But with IE10 I'm getting
XMLHttpRequest: Network Error 0x80070005, Access is denied.
and with Chrome on my Android phone I'm getting
error 405 (Method not allowed).
It's also failing with Firefox on the phone (just reports 'web error'), but I haven't any debugger for that so can't check the underlying error.
On an iPad (using Safari), the browser just crashes with no message.
The method being accessed first is 'Login', but if I comment that out, hardcode my login details and try another method (GetLocations) I'm getting the same error.
The site is quilkin.co.uk, if anyone feels like having a look. If it's working correctly, you should get an 'invalid user' or 'invalid password' if you try to log in. Yes, I know it's not secure! I'll sort that later.
The web.config is as follows (sorry about the bad formatting):
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
<customErrors mode="Off"/>
<compilation debug="true" targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5.2"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<handlers>
<remove name="WebDAV"/>
</handlers>
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept,Authorization" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, ORIGIN" />
</customHeaders>
</httpProtocol>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
</modules>
<directoryBrowse enabled="true"/>
<validation validateIntegratedModeConfiguration="false"/>
</system.webServer>
</configuration>
The 'WebDAV' removal lines were added as a result of looking at other posts, but appeared to make no difference.
I also tried adding a new 'global.asax' as described here but that didn't help either.

i guess i now the problem. please use * in [ServiceContract]. like this:
[WebInvoke(Method = "*"
this way you allow your method receive options request.
Enabling CORS for non-GET requests requires more than just setting the
Access-Control-Allow-Origin header - it also needs to deal with
preflight requests, which are OPTIONS requests which ask the server
whether it's safe to perform operations which can potentially change
data (e.g., POST, PUT, DELETE) before the actual request is sent.
I've written a blog post about adding CORS support for WCF. It's not the simplest of the implementations, but hopefully the code in the post can be simply copied / pasted into your project. The post can be found at http://blogs.msdn.com/b/carlosfigueira/archive/2012/05/15/implementing-cors-support-in-wcf.aspx.

At last I have found the solution (or a solution). This thread's second answer was the key. Basically I had to add an extra (empty) method for each POST method, to deal with the OPTIONS request that some browsers are sending, e.g.:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/Login", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
Login Login(Login login);
[OperationContract]
[WebInvoke(Method = "OPTIONS", UriTemplate = "/Login", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
Login LoginOptions(Login login);

Related

.Net Core 2.1 Error 413 on multipart/form-data POST only on IIS not IIS Express

I'm hitting a problem with multipart/form-data POST uploads on IIS. My client is an Angular SPA and my backend is on .Net Core 2.1 (I know it's old).
The backend project is published as Self-Contained win-x64. I'm not sure how it's configured exactly on IIS / Kestrel but the IIS App runs under a specific Application Pool (No managed Code / Integrated). My web.config looks like this:
<configuration>
<location path="." inheritInChildApplications="false">
<system.web>
<httpRuntime maxRequestLength="1048576" />
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath=".\my.app.exe" stdoutLogEnabled="false" stdoutLogFile=".\log\path" />
</system.webServer>
</location>
</configuration>
In my development environment instead I'm using IIS Expres.
Now I added a multipart/form-data upload, sending form data together with a blob/image. This worked out of the box in development settings. However when I publish to staging environment with real IIS and the above web.config, I always get 413 Request entity too large.
My controller looks like this:
[HttpPost]
[DisableRequestSizeLimit]
[RequestFormLimits(MultipartBodyLengthLimit = int.MaxValue, ValueLengthLimit = int.MaxValue)]
[RequestSizeLimit(int.MaxValue)]
[Route("my/route")]
public ActionResult MyHandler()
I also added limits for Kestrel in Program.cs:
.UseKestrel(options =>
{
options.Limits.MaxRequestBodySize = 104857600; // 100MB
}
)
And to make the weirdness complete the 413 in staging environment only happens in Firefox. I have no idea what else I can do. I also cleared cache in firefox.
After longer search I finally found the necessary setting in IIS to make this work in Firefox. And it has indeed be mentioned in a few sources as the 'last option'. For me it was necessary in this case.
In 'IIS Manager' I selected the backend application and opened 'Configuration Editor'
system.webServer/serverRuntime -> uploadReadAheadSize=2147483647
That maked it work.

IIS caching and HTTP caching

What's the difference between
<caching enabled="true" enableKernelCache="true">
<profiles>
<add extension="*" location="Any" policy="CacheForTimePeriod" duration="00:30:00" varyByQueryString="*" varyByHeaders="Accept-Language" kernelCachePolicy="CacheUntilChange" />
</profiles>
</caching>
and
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="private, max-age=1800, must-revalidate" />
<add name="Pragma" value="private, max-age=1800, must-revalidate" />
<add name="Expires" value="1800" />
</customHeaders>
</httpProtocol>
If I understand well, the first is for IIS (cache file on server, to answer quickly) and the second one is for proxy/client (ask a new version every 30 minutes) ?
What do you think about my cache policies ? I want to improve performance but because I have important fresh information every 30min, I set to 30 min every cache...
The Pragma header is implementation specific and secondary to the Cache-Control header (see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.32). Better to not use it.
Setting the cache to "private" prevents caching on proxies, you might want to set it to "public" for faster client response--this change is especially recommended if your content is served over HTTP rather than HTTPS ("public" is ignored in that case, unless SSL is cracked within for instance a corporate fire-wall).

Visual Studio debugging with windows auth not working

I have an ASP.NET webforms application that uses windows authentication when developing locally. The first time that I debug the webapp, IIS Express starts up and the pages work as expected. If I stop debugging and then start it again, I get in this endless cycle that no matter what page I go to, it always forwards to the login.aspx page and then to my Default.aspx page.
I can keep clicking on different pages, but it still keeps going to the Login then Default. I should be authenticated at this point and not be forwared to login.aspx. I believe it is because IIS express thinks that I am not authenticated. However, when I look at my cookies, I see that there is a ASP.NET_SessionId cookie so I don't think this should be happening.
If this helps, I have this in my page_load for login.aspx
if (authSection.Mode == AuthenticationMode.Windows)
{
//stuff happens here
Response.Redirect("Default.aspx");
return;
}
To fix the problem, I have to kill IIS express and start debugging again. I'm not really sure why it thinks that I am not authenticated. Even though this isn't the same question, I tried the answer provided here: https://stackoverflow.com/a/19515891/888617 and it did not help.
Edit: This actually doesn't appear to solve my issue.
It turns out the issue was specific to Chrome. I was getting this issue when debugging and had to kill the IIS express process for it to resolve itself. However, I found a more perminate solution by doing the following.
In %userprofile%\documents\IISExpress\config\applicationhost.config insure that the overrideModeDefault is set to allowed for windowsAuthentication and anonymousAuthentication like this:
<section name="anonymousAuthentication" overrideModeDefault="Allow" />
<section name="windowsAuthentication" overrideModeDefault="Allow" />
Your authentication section should also look like this. Note the only provider is NTLM.
<authentication>
<anonymousAuthentication enabled="false" userName="" />
<basicAuthentication enabled="false" />
<clientCertificateMappingAuthentication enabled="false" />
<digestAuthentication enabled="false" />
<iisClientCertificateMappingAuthentication enabled="false">
</iisClientCertificateMappingAuthentication>
<windowsAuthentication enabled="true">
<providers>
<add value="NTLM" />
</providers>
</windowsAuthentication>
</authentication>
This section should also be in the web.config.
<authentication>
<windowsAuthentication enabled="true">
<providers>
<clear />
<add value="NTLM" />
</providers>
</windowsAuthentication>
</authentication>

How do I debug AuthorizeAttribute and FormsAuthentication calls

I am having crazy problems with Forms Authentication, with the AuthorizeAttribute, and 302 redirect loops. I need to find out what is going on. Is there anyway I can debug Forms Authentication and the AuthorizeAttribute?
Just some more details, in case it is important:
I am using custom membership provider and role provider. I have the correct methods implemented and doing the reading for User/Roles from my custom database tables.
I have the following in my web.config to point to my custom providers:
<membership defaultProvider="MyMembershipProvider">
<providers>
<clear />
<add name="MyMembershipProvider" type="Domain.Entities.Security.MyMembershipProvider" connectionStringName="MyDB" MinRequiredPasswordLength="8" MaxInvalidPasswordAttempts="5" MinRequiredNonAlphanumericCharacters="0" applicationName="My App Name" />
</providers>
</membership>
<profile enabled="false">
<providers>
<clear />
</providers>
</profile>
<roleManager enabled="true" defaultProvider="MyRoleProvider" cookieTimeout="2800" cookieSlidingExpiration="true" cacheRolesInCookie="true">
<providers>
<clear />
<add name="MyRoleProvider" type="Domain.Entities.Security.MyRoleProvider" connectionStringName="MyDB" applicationName="/" />
</providers>
</roleManager>
Some of my controller/actions are 'open'. Some of them have the 'Authorize[Roles="admin"]' and similar.
Sometimes I can work on the application for hours without anything happening. Sometimes I hit a 302 redirect loop soon after I login and then I try to go into one of the other pages. Once that happens, I cannot even go into the top level path without it going into a 302 redirect loop sometimes.
Any directions, any pointers, any suggestions would be greatly appreciated.
Please see the answer in the question linked. This was the resolution to the redirect loop problem.
IIS Session timeout and Forms Authentication loop

Html.Telerik().StyleSheetRegistrar() output file generating 404 message on asset.axd

I'm using the Telerik controls form MVC and they work great in my work/home dev environments, and in the work prod environment, but when I tried to deploy to my home prod environment (IIS7) I get a problem.
I've added the axd mime type, but wan't sure what else to do.
I read a post suggesting adding a handler, but wasn't sure if I'm setting that wrong or I'm just looking in the wrong direciton.
if you're on IIS7 make sure you add the handler to the <system.webServer><handlers> section:
<add name="MyName" path="MyName.axd" verb="*" type="NameSpace.Class, Assembly" />
I added: <add name="ScriptRegistrar" path="Access.axd" verb="*" type="Telerik.Web.Mvc.UI.ScriptRegistrar, Version=v2.0.50727" />
http://localhost:1000/asset.axd?id=sQAAAB-LCAAAAAAABADsvQdgHEmWJSYvbcp7f0r1StfgdKEIgGATJNiQQBDswYjN5pLsHWlHIymrKoHKZVZlXWYWQMztnbz33nvvvffee--997o7nU4n99__P1xmZAFs9s5K2smeIYCqyB8_fnwfPyJ-8UfT9qNHH7X5u_butGk-Gn10SX_u7ezujHfH93Ye0gfTjx619TqnX2YfPbr36f3RR_Tze7_4oxU1PKmWbb5s775ur8scb5_zV9VHj3ZGHy2pwbRaLKrlGKB_yYi_2JUv2rzM6-LtuN9gL2xwWTRtJt9__5d8_5f8PwEAAP__qtxwmrEAAAA%3d
To enable web resource combining with the Telerik Extensions you need to register the WebAssetHttpHandler in your webconfig:
IIS 7
<add name="AssetHandler" preCondition="integratedMode" verb="GET,HEAD" path="asset.axd" type="Telerik.Web.Mvc.WebAssetHttpHandler, Telerik.Web.Mvc"/>
IIS 6
<add verb="GET,HEAD" path="asset.axd" validate="false" type="Telerik.Web.Mvc.WebAssetHttpHandler, Telerik.Web.Mvc"/>
This handler enables you to use the Combine, Compress, and Cache features of the Script and StyleSheet Registrars. You can learn more and see additional config details in the Telerik online docs:
http://www.telerik.com/help/aspnet-mvc/web-assets-working-with-javascript-web-assets.html

Resources