MVC5 anonymous access failing for new pages - c#

I'm a noob when it comes to MVC security as I usually use my own, so please bear with me.
I have an MVC5 application which I'm using pretty-much straight out of the box.
It all works fine when I run it locally but after I have deployed it to a remote webserver I have authentication issues.
The pages which come with the project as standard open fine (Home, About, etc) but when I try to open one of my own I get this error:
Login failed. The login is from an untrusted domain and cannot be used
with Windows authentication.
The error is being raised on the first line of the view that tries to reference the model.
I haven't added anything to the web.config to allow or deny authentication.
An extract from the config looks like this:
<system.web>
<authentication mode="None" />
<compilation targetFramework="4.5.1" />
<httpRuntime targetFramework="4.5.1" />
</system.web>
<system.webServer>
<modules>
<remove name="FormsAuthenticationModule" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="LessAssetHandler" path="*.less" verb="GET" type="BundleTransformer.Less.HttpHandlers.LessAssetHandler, BundleTransformer.Less" resourceType="File" preCondition="" />
</handlers>
<security>
<authorization>
<add accessType="Allow" users="?" />
</authorization>
</security>
</system.webServer>
What do I need to do to allow access to the other pages?
[Edit]
The Home controller works fine. It is the standard out-of-the-box one which looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace ASP.NET_MVC5_Bootstrap3_3_1_LESS.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
}

This was a SQL server problem, not ASP authentication as I had thought.
The server name in the connection string was the fully qualified version, e.g.:
server.domain.local
Changing this to its short version server fixed this issue!

Related

How to allow anonymous authentication for index in owin pipeline?

My index page in a MVC 5 Application return an unauthorized status code.
I have configured my application under IIS 10.0 with none authentication to manage the authentication in the owin pipeline :
<system.web>
<compilation debug="true" targetFramework="4.7.1" />
<httpRuntime targetFramework="4.7.1" />
<authentication mode="None" />
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<clear />
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/>
</handlers>
</system.webServer>
Here my controller to allow anonymous on index action :
[Authorize]
public class SPAController : Controller
{
[AllowAnonymous]
public ActionResult Index()
{
return View();
}
}
And my owin pipeline where i suspect that i miss something :
// Enable static file serving for the current application before authentication phase
app.UseStaticFiles(new StaticFileOptions() {
RequestPath = new PathString(""),
FileSystem = new PhysicalFileSystem(HostingEnvironment.MapPath("~/"))
});
Update
I also tried this without success :
[Authorize]
public class SPAController : Controller
{
[OverrideAuthorization]
[AllowAnonymous]
public ActionResult Index()
{
return View();
}
}
and without attributes

Getting PUT and DELETE verbs in WebAPI2 to work on IIS 8.5

I am attempting to publish code to my company test web server and I'm getting a multitude of errors returned from IIS when attempting to call any methods using the PUT or DELETE verb. I've researched this particular issue, and all of the results that I've attempted either do nothing, or generate a new error. When I try with the default system.webServer configuration I receive the general 405 method not allowed error, here's that portion of the web.config:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
From digging through Google and several stack articles, the majority of accepted answer specify to remove WebDAV through the web config file, which I've done, and here's that updated code:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="WebDAV" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
When I try using just removing the WebDAV handler, I continue to get the 405 method not allowed error, but as soon as I remove the WebDAVModule, my error becomes a 500 Internal Server Error, and viewing from the server doesn't actually give me any further information.
I've also attempted suggestions revolving around removing and adding the "ExtensionlessUrlHandler-ISAPI-4.0_32bit" & "ExtensionlessUrlHandler-ISAPI-4.0_64bit" handlers, with the same results (405 when don't remove the WebDAVModule or 500 when I do remove it).
Here's the methods on my WebApi controller that I'm attempting to call, maybe this is the problem, though it works just fine in my development environment:
public string PutRegistrationBatch(RegistrationBatch Model) {
// Code to save the model to our database
}
public string DeleteRegistrationBatch(RegistrationBatch Model) {
// Code to delete the item from the database
}
UPDATE
I ran a trace on the application and I'm seeing GET and POST commands get through to the site, however none of the PUT or DELETE commands get through to the site:
1/10/2017 1:22:41 PM /api/RegistrationBatch/ 200 GET
1/10/2017 1:22:55 PM /api/RegistrationBatch/ 200 POST
It seems as though the PUT and DELETE commands are being filtered out and refused at the host level and never making into my application.
UPDATE
It seems that WebDAV is the underlying issue, but we run a web service that utilizes this technology, so removing it is not an option until we can update that service. In the mean time, I've found that a work around outlined by Scott Hanselman here (http://www.hanselman.com/blog/HTTPPUTOrDELETENotAllowedUseXHTTPMethodOverrideForYourRESTServiceWithASPNETWebAPI.aspx) allows for me to send PUT and DELETE requests as a POST request.
I wouldn't suggest that is is an answer to the problem, but it at least allows me to work around the problem until such a time as we can uninstall WebDAV and hopefully that will allow my Web Api 2 application(s) to work properly.
You need to apply the [HttpPut] and [HttpDelete] attributes on the respective actions
[HttpPut]
public string PutRegistrationBatch(RegistrationBatch Model) { ... }
[HttpDelete]
public string DeleteRegistrationBatch(RegistrationBatch Model) { ... }
And in the config file you should also try to use the specific verbs you want to allow
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
If you have the WebDAV IIS feature installed, it can cause conflicts with Put, Delete, and Patch requests (maybe more... can't remember). You can either uninstall the feature server-wide or manually remove the HttpModule and HttpHandlers from the system.webServer element to target this specific application. See https://stackoverflow.com/a/26003440/179223
I remember getting into similar ditch sometime ago. Eventually this worked for me.
Reset all module configurations of 'Default Web Site' and your website to default values in IIS. You can do this by
1. Select your website, double click "Modules"
2. Click on "Revert to Parent" link under Actions panel on right side
Use the following into your Web.config
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" runManagedModulesForWebDavRequests="true">
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>

Some of my asp.net api attribute based routing are returning 404 (not found)

In the asp.net mvc 5 + web api 2 am working on, some of the webapi routes that I defined are not working, while some are working perfectly. I can't seem to identify what the problem is. And before you ask I have read the whole SO questions and applied all the solutions I can find, but none of it seems to work in my current situation. I also checked, double checked and yet I can't figure out why. Here are some of the configurations and route registrations that I think affects web api.
Route definition
[HttpPost]
[Route("FollowApi/{profileId:int}/FollowClient" Name = "FollowClient")]
Application_start configuration
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
Webconfig configuration
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
<add name="ImageResizingModule" type="ImageResizer.InterceptModule" />
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Please, any help or pointers as to why this problem is occurring will be seriously appreciated as I am in a time constrained situation.
Edit
Working api
public class CommonApiController : BaseApiController
{
[Authorize]
[HttpGet]
[Route("Client/GetInfoCounts")]
public IHttpActionResult GetInfoCounts()
{
//Method body
}
}
Not working api
public class FollowApiController : BaseApiController
{
[HttpPost]
[Route("FollowApi/{profileId:int}/FollowClient")]
public IHttpActionResult Follow(int profileId)
{
//Method body
}
}
It looks like the RoutePrefix on the controller was not included in the client call. My take away from this is that it makes sense to have a certain pattern for troubleshooting these kind of problems.
Something like:
Is the url correct?
Is the httpMethod correct?
Are the parameters named correctly?

HttpContext.User NullReferenceException only on deployed server

I am using formsauthentication on my MVC project and when testing locally using the Visual Studio Development Server everything works as expected. Once deployed to IIS 7.5 the HTTPContext.User is causing NullReferenceExceptions.
Both Dev and Prod machines are using the same SQL db (at the moment - this will change post-deployment of course) so I know it is not a problem with the DB or data within.
This must be a setting in IIS or my web.config but I cannot find it.
I've tried various changes to my web.config(from suggestions I've found around SE), here is part of my web.config for the current implementation:
<appSettings>
<add key="autoFormsAuthentication" value="true" />
<add key="enableSimpleMembership" value="false" />
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
****Snip****
<system.web>
<httpRuntime targetFramework="4.5" />
<compilation debug="true" targetFramework="4.5" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" cookieless="UseCookies"/>
</authentication>
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
<add namespace="ProjectSquid.WebUI.HTMLHelpers" />
</namespaces>
</pages>
<roleManager enabled="true" defaultProvider="CustomRoleProvider">
<providers>
<clear />
<add name="CustomRoleProvider"
type="Project.Domain.Filters.CustomRoleProvider"
connectionStringName="EFDbContext"
enablePasswordRetrieval="false"
cacheRolesInCookie="true"/>
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear />
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="EFDbContext" />
</providers>
</sessionState>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-UA-Compatible" value="IE=9" />
</customHeaders>
</httpProtocol>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<modules runAllManagedModulesForAllRequests="false">
<remove name="FormsAuthentication" />
<remove name="DefaultAuthentication" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" preCondition="" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" preCondition="" />
<remove name="UrlRoutingModule-4.0"/>
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" preCondition="" />
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
</modules>
</system.webServer>
What could cause HttpContext.User to differ from the VS Development Server and the IIS 7.5 implementation?
EDIT:
HttpContext is fed through the inherited BaseController:
protected virtual new CustomPrincipal User
{
get { return HttpContext.User == null? null : HttpContext.User as CustomPrincipal; }
}
public new HttpContextBase HttpContext
{
get
{
return ControllerContext == null ? null : ControllerContext.HttpContext;
}
}
The cookie isn't created until the PostAuthenticationRequest:
public void MvcApplication_PostAuthenticationRequest(object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
string encTicket = authCookie.Value;
if (!String.IsNullOrEmpty(encTicket))
{
var ticket = FormsAuthentication.Decrypt(encTicket);
var id = new UserIdentity(ticket);
string[] userRole = Roles.GetRolesForUser(id.Name);
var prin = new CustomPrincipal(id);
HttpContext.Current.User = prin;
Thread.CurrentPrincipal = prin;
}
}
}
The authentication itself appears to be working fine as the function causing the exception starts with [Authorize] and successfully begins executing but fails as null when it reaches the first User reference:
int userT = User.Team.TeamId;
In this context the User being CustomPrincipal BaseController.User.
EDIT2:
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880"
cookieless="UseCookies"
name=".ASPXAUTH"
protection="All"
slidingExpiration="true"/>
</authentication>
EDIT3
Custom IIdentity:
[Serializable]
public class UserIdentity : MarshalByRefObject, IIdentity
{
private readonly FormsAuthenticationTicket _ticket;
public UserIdentity(FormsAuthenticationTicket ticket)
{
_ticket = ticket;
}
public string AuthenticationType
{
get { return "Custom"; }
}
public bool IsAuthenticated
{
get { return !string.IsNullOrEmpty(this.Name); }
}
public string Name
{
get { return _ticket.Name; }
}
public string UserId
{
get { return _ticket.UserData; }
}
public bool IsInRole(string Role)
{
return Roles.IsUserInRole(Role);
}
public IIdentity Identity
{
get { return this; }
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (context.State == StreamingContextStates.CrossAppDomain)
{
GenericIdentity gIdent = new GenericIdentity(this.Name, this.AuthenticationType);
info.SetType(gIdent.GetType());
System.Reflection.MemberInfo[] serializableMembers;
object[] serializableValues;
serializableMembers = FormatterServices.GetSerializableMembers(gIdent.GetType());
serializableValues = FormatterServices.GetObjectData(gIdent, serializableMembers);
for (int i = 0; i < serializableMembers.Length; i++)
{
info.AddValue(serializableMembers[i].Name, serializableValues[i]);
}
}
else
{
throw new InvalidOperationException("Serialization not supported");
}
}
Custom IPrincipal:
interface ICustomPrincipal : IPrincipal
{
int Id { get; set; }
string Name { get; set; }
string Role { get; set; }
}
public class CustomPrincipal : IPrincipal
{
public CustomPrincipal(UserIdentity identity)
{
this.Identity = identity;
}
public IIdentity Identity { get; private set; }
Most likely, you are attempting to retrieve HttpContext.User before it has been initialized. This behavior differs between IIS Classic (or the Visual Studio Web Server) and IIS Integrated pipeline modes, which would explain why you are seeing different behavior between the environments.
Explanation
HttpContext is part of an application's runtime state. In modern hosting environments (IIS integrated pipeline mode and OWIN), HttpContext is not populated until after the Application_Start method is complete. Any behavior that you have that requires HttpContext.User should not be executed until the Application_BeginRequest event or after.
Reference: Request is not available in this context
It's not clear from your post since configuring the authentication depends on various settings in your project plus the configuration file. For example in Web.config file, there are several places to customize/configure the authentication like this one (the most important rule) that you haven't placed in your post:
<system.web>
<authentication mode="" />
</system.web>
As you know, since the configuration system is based on a hierarchical system of management system that uses **.config* files, you should consider the defaults, perhaps by <remove/> or <add/> some parameters. The configuration files for IIS 7 and later are located in your %WinDir%\System32\Inetsrv\Config folder, and the primary configuration files are:
ApplicationHost.config - This configuration file stores the settings for all your Web sites and applications.
Administration.config - This configuration file stores the settings for IIS management. These settings include the list of
management modules that are installed for the IIS Manager tool, as
well as configuration settings for management modules.
Redirection.config - IIS 7 and later support the management of several IIS servers from a single, centralized configuration file.
This configuration file contains the settings that indicate the
location where the centralized configuration files are stored.
Note: Some settings can be delegated to Web.config files, which may override settings in the ApplicationHost.config file. In addition, settings that are not delegated cannot be added to Web.config files.
Tip: A default installation of IIS 7 does not contain Digest authentication, so adding the settings for Digest authentication to your ApplicationHost.config will have no effect or may cause errors until the Digest authentication module is installed.
You need to see both local and deployment configurations to meet your purpose. If you have trouble with integrated pipeline, see the following pages to take its advantages :
Debugging the IIS7 integrated pipeline with failed request
tracing
How to Take Advantage of the IIS 7.0 Integrated Pipeline
Update About SlidingExpiration : According to MSDN:
Sliding expiration resets the expiration time for a valid
authentication cookie if a request is made and more than half of the
timeout interval has elapsed.
If the cookie expires, the user must re-authenticate. Setting the SlidingExpiration property to false can improve the security of an application by limiting the time for which an authentication cookie is valid, based on the configured timeout value. So I think there's no need to use this as false. This means It will expire cache after time period at the time of activating cache if any request is not made during this time period. This type of expiration is useful when there are so many data to cache. So It will put those items in the cache which are frequently used in the application. So it will not going to use unnecessary memory.

Dot character '.' in MVC Web API 2 for request such as api/people/STAFF.45287

The URL I'm trying to let work is one in the style of: http://somedomain.com/api/people/staff.33311 (just like sites as LAST.FM allow all sort of signs in their RESTFul & WebPage urls, for example "http://www.last.fm/artist/psy'aviah" is a valid url for LAST.FM).
What works are following scenarios:
- http://somedomain.com/api/people/ - which returns all people
- http://somedomain.com/api/people/staff33311 - would work as well, but it's not what I'm after
I'd want the url to accept a "dot", like the example below
- http://somedomain.com/api/people/staff.33311 - but this gives me a
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I've set up following things:
The controller "PeopleController"
public IEnumerable<Person> GetAllPeople()
{
return _people;
}
public IHttpActionResult GetPerson(string id)
{
var person = _people.FirstOrDefault(p => p.Id.ToLower().Equals(id.ToLower()));
if (person == null)
return NotFound();
return Ok(person);
}
The WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
I already tried following all the tips of this blogpost http://www.hanselman.com/blog/ExperimentsInWackinessAllowingPercentsAnglebracketsAndOtherNaughtyThingsInTheASPNETIISRequestURL.aspx but it still won't work.. I also think it's quite tedious and I wonder if there isn't another, better and more secure way.
We have our Id's internally like this, so we're going to have to find a solution to fit the dot in one way or another, preferably in the style of "." but I'm open to alternative suggestions for urls if need be...
Suffix the URL with a slash e.g. http://somedomain.com/api/people/staff.33311/ instead of http://somedomain.com/api/people/staff.33311.
Following setting in your web.config file should fix your issue:
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
I've found that adding the following before the standard ExtensionlessUrlHandler solves the issue for me:
<add name="ExtensionlessUrlHandler-Integrated-4.0-ForApi"
path="api/*"
verb="*"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
I don't think the name actually matters all that much except it probably helps if your IDE (Visual Studio in my case) is managing your site configuration.
H/T to https://stackoverflow.com/a/15802305/264628
I don't know what I am doing really, but after playing with the previous answer a bit I came up with another, perhaps more appropriate, solution:
<system.webServer>
<modules>
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
</modules>
</system.webServer>
I found that I needed to do more than just set the runAllManagedModulesForAllRequests attribute to true. I also had to ensure that the extensionless URL handler was configured to look at all paths. In addition, there is one more bonus configuration setting you can add which will help in some cases. Here is my working Web.config:
<system.web>
<httpRuntime relaxedUrlToFileSystemMapping="true" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<remove name="WebDAV" />
<remove name="OPTIONSVerbHandler" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Note, specifically, that the ExtensionlessUrlHandler-Integrated-4.0 has its path attribute set to * as opposed to *. (for instance).
I'd use this in Web.config file:
<add name="ManagedSpecialNames" path="api/people/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
before standard "ExtensionlessUrlHandler".
For instance in my case I put it here:
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ManagedFiles" path="api/people/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
So you force URLs of such pattern to be managed by you, instead of standard management as files in application directory tree.
I got stuck in this situation but appending /
at the end of URL wasn't look clean for me.
so just add below in web.config handlers tag
and you will be good to go.
<add name="Nancy" path="api" verb="*" type="Nancy.Hosting.Aspnet.NancyHttpRequestHandler" allowPathInfo="true" />
I found that both way works for me: either setting runAllManagedModulesForAllRequests to true or add ExtentionlessUrlHandler as following. Finally i choose to add extensionUrLHandler since runAllManagedModulesForAllRequests do have performance impact to the site.
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<remove name="WebDAV" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*" verb="*"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
I also faced this issue. I was under a circumstance where I was not supposed to play with IIS and website config related settings. So I had to make it working by making changes at the code level only.
The point is that the most common case where you would end up having dot character in the URL is when you get some input from the user and pass it as a query string or url fragment to pass some argument to the parameters in the action method of your controller.
public class GetuserdetailsbyuseridController : ApiController
{
string getuserdetailsbyuserid(string userId)
{
//some code to get user details
}
}
Have a look at below URL where user enters his user id to get his personal details:
http://mywebsite:8080/getuserdetailsbyuserid/foo.bar
Since you have to fetch some data from the server we use http GET verb. While using GET calls any input parameters can be passed only in the URL fragments.
So to solve my problem I changed the http verb of my action to POST. Http POST verb has the facility of passing any user or non-user input in body also. So I created a JSON data and passed it into the body of the http POST request:
{
"userid" : "foo.bar"
}
Change your method definition as below:
public class GetuserdetailsbyuseridController : ApiController
{
[Post]
string getuserdetailsbyuserid([FromBody] string userId)
{
//some code to get user details
}
}
Note: More on when to use GET verb and when to use POST verb here.

Categories