I'm trying to implement an OData collection function that receives two DateTimeOffset? parameters (MinSentOn and MaxSentOn) and will return some summary information from an Orders table, but I'm having routing problems when I pass the time part of the DateTimeOffset, receiving an HTTP Error 500.0 - Internal Server Error directly from IIS, because it seems it's trying to reach a file and not the controller itself.
This is my current OData configuration:
odataBuilder.Namespace = "D";
var fc =
odataBuilder.EntityType<Order>().Collection
.Function("ToExecutiveSummary")
.Returns<ExecutiveSummary>();
fc.Parameter<DateTimeOffset?>("MinSentOn");
fc.Parameter<DateTimeOffset?>("MaxSentOn");
This is the function in my controller:
[HttpGet]
public async Task<IHttpActionResult> ToExecutiveSummary(DateTimeOffset? minSentOn, DateTimeOffset? maxSentOn, CancellationToken ct)
{
return await _uow.ExecuteAndCommitAsync(async () =>
{
var query = _uow.Orders.Query();
if (minSentOn != null) query = query.Where(e => e.SentOn >= minSentOn.Value);
if (maxSentOn != null) query = query.Where(e => e.SentOn <= maxSentOn.Value);
// TODO needs optimization, test only
var executiveSummary =
query.Select(e =>
new ExecutiveSummary
{
TotalOrders = query.Count(),
TotalProducts = query.Sum(ex => ex.Quantity),
TotalPharmacies = query.GroupBy(ex => ex.Pharmacy.Id, ex => ex.Pharmacy.Id).Count()
}).FirstOrDefault();
return Ok(executiveSummary);
}, ct);
}
Snippet of the web.config changes to support the OData path and solve some routing problems I faced until I hit this wall, like dots or double escapes (changes have comments):
<configuration>
<!-- ... -->
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<!-- Removed : and % from the path filter -->
<httpRuntime targetFramework="4.5.2" requestPathInvalidCharacters="<,>,*,&,\,?"/>
<globalization uiCulture="pt-PT" culture="pt-PT" />
</system.web>
<!-- ... -->
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<!-- to support the dot (.) for functions or actions -->
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="/*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<security>
<!-- to support double escapings, like 2015-08-10%2000:00:00.0000%2B01:00 -->
<requestFiltering allowDoubleEscaping="true"/>
</security>
</system.webServer>
<!-- ... -->
</configuration>
Now, during my testings, I'm facing the following:
If I don't pass the time part (example: http://localhost:58806/odata/Order/D.ToExecutiveSummary(MinSentOn=null,MaxSentOn=2015-08-10) ) the request reaches my code without any problem, making me believe that there aren't any problem with the OData configuration and route.
But when I include the time part (example: http://localhost:58806/odata/Order/D.ToExecutiveSummary(MinSentOn=null,MaxSentOn=2015-08-10%2000:00:00.0000%2B01:00) ) I receive an Internal Server Error (image attached) directly from the IIS. It seems it is trying to resolve to a file instead to the controller, whence the problem.
Ultimately, I know I could receive the parameters as strings and make the parse myself, but I would like to implement this without using the "hammer" :)
I do think you can use the parameter alias for DateTimeOffset parameter value.
For example:
http://localhost:58806/odata/Order/D.ToExecutiveSummary(MinSentOn=null,MaxSentOn=#p)?#p=2015-08-10%2000:00:00.0000%2B01:00
In the following Uri, you can find many parameter alias examples:
https://github.com/OData/WebApi/blob/master/OData/test/UnitTest/System.Web.OData.Test/OData/Formatter/ODataFunctionTests.cs#L24-L43
Moreover, in http://odata.github.io/WebApi/#04-06-function-parameter-support, you can find a simple guidance about function parameter.
However, the issue is a known issue related to IIS and be tracked on odata Web APi#github
Thanks.
I finally found the problem! It was related to the DateTimeOffset format I was using. I was forgetting the T, and writing 2015-08-10 00:00:00.0000%2B01:00 instead of 2015-08-10T00:00:00.0000%2B01:00 and it couldn't parse correctly.
What confused me was IIS throwing an Internal Server Error instead of some Bad Request or Not Found, and because the application exception handler wasn't being invoked, so I assumed the format was ok but IIS was having some problem with the path having unusual characters.
#Sam Xu suggestion lead me in the right path, because even using alias (I didn't know OData had support for parameter alias - thanks for that!) it was still throwing the exception...
In the end, it was a failure of mine, even if the server response should have been more enlightening...
You need to cast it to a DateTimeOffset like this:
cast(2015-08-10%2000:00:00.0000%2B01:00,Edm.DateTimeOffset)
Source: https://github.com/OData/WebApi/blob/master/OData/test/E2ETest/WebStack.QA.Test.OData/DateAndTimeOfDay/DateAndTimeOfDayTest.cs#L181
Related
I am trying to setup a .net core 2.2 web api to use a post verb. Anything other than a get verb returns a 405 no matter if it is run on my local machine (w10 iis eXPRESS 10.0) or the windows server (2016 R2 IIS 8.0). I've read the other posts about disabling WebDav in your config file, adding a route, and completely removing the WebDav feature. I have done all of those to no avail. I'm just starting to develop in core and find this baffling, on the same server is a non-core web api that runs on .net framework 4.5 that processes GET,PUT,POST,DELETE without error. And yes, I have restarted the server after making changes to any of the configurations. The following are the web.config changes that I made, the last one coming directly from MS. Basic project that reproduces the same error on my machine and server is here https://github.com/FranciscanMedia/error405_core/tree/master it is just a standard web api project you get when you fire up VS2019.
<system.webServer>
<handlers accessPolicy="Read, Script">
<remove name="WebDAV" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<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" />
</handlers>
</system.webServer>
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
</handlers>
</system.webServer>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebDAVModule"/>
</modules>
</system.webServer>
<system.webServer>
<handlers accessPolicy="Read, Script">
<remove name="WebDAV" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<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" />
</handlers>
</system.webServer>
Short answer
It could be as simple as that. The reason is routing.
Just send your POST request to right URL like https://localhost:44327/api/values/123.
Detailed explanation
It's not the issue. It works as expected.
You make a GET request to https://localhost:44327/api/values/. It returns 200 OK.
But when you make a POST request to the same URL https://localhost:44327/api/values/. It says 405 Method not allowed.
However, you get 405. It is happening because you are hitting the GET endpoint with POST method.
Microsoft Docs says:
... the HTTP client sent a valid JSON request to the URL for a Web API application on a web server, but the server returned an HTTP 405 error message which indicates that the PUT method was not allowed for the URL. In contrast, if the request URI did not match a route for the Web API application, the server would return an HTTP 404 Not Found error.
https://learn.microsoft.com/en-us/aspnet/web-api/overview/testing-and-debugging/troubleshooting-http-405-errors-after-publishing-web-api-applications
If you simply remove the GET endpoint. The POST request will start returning 404 Not found. Which means that you are not hitting any registered route.
To send POST request you need to use different URL according to the routing rules.
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// POST api/values
[HttpPost("{val}")]
public StatusCodeResult Post()
{
return Ok();
}
}
This attribute-based configuration means that route of your POST endpoint is /api/Values/{val}. Where {val} is any value. It's not processed in the endpoint.
If you want to process it, you should pass it to the method:
[HttpPost("{val}")]
public StatusCodeResult Post(string val)
{
return Ok();
}
I think that in your controller you have to import another library.
Try
using System.Web.Http;
Instead of
using Microsoft.AspNetCore.Mvc
Looking at what you have defined:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
Then for the action:
[HttpPost("{val}")]
public StatusCodeResult Post()
{
return Ok();
}
Your routing matches the following url:
https://localhost:44327/api/values/StatusCodeResult
It is going to take your main route defined on your controller [Route("api/[controller]")]
Then you are defining the "template" to use "{val}"
This is telling it to use the ActionResult specific name and to expect var val to be passed/appened.
Checking out the official documentation here: https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-2.2
under section "Token replacement in route templates ([controller], [action], [area])"
They specifiy:
For convenience, attribute routes support token replacement by enclosing a token in square-braces ([, ]). The tokens [action], [area], and [controller] are replaced with the values of the action name, area name, and controller name from the action where the route is defined. In the following example, the actions match URL paths as described in the comments:
[Route("[controller]/[action]")]
public class ProductsController : Controller
{
[HttpGet] // Matches '/Products/List'
public IActionResult List() {
// ...
}
[HttpGet("{id}")] // Matches '/Products/Edit/{id}'
public IActionResult Edit(int id) {
// ...
}
}
If you want it to just route based on just verbs (follow a pattern where each api endpoint just handles operations for that specific object) then you would change your post method to just
[HttpPost]
public ActionResult Post(string val)
{
return Ok();
}
I totally agree with #Vladimir's answer. I dont have enough points to add comments to the answer by #vlaimir so i am adding my thoughts and suggestions.
The code you have on your github,
// POST api/values
[HttpPost("{val}")]
public StatusCodeResult Post()
{
return Ok();
}
This is a post and it would expect a value {val} per the route action configuration. Since you may try to hit the post without any value, thats not permitted. Ensure you supply some value and then do the POST. If you are using POSTMAN, you may have to supply the BODY of your request with some value. Swagger is a great util tool to embed into the web api's and that comes with excellent intuitive UI for our routes/resources. That might be even ideal to help determine and ensure you supply the right value.
Otherwise, you dont need to modify or worry about your IIS or IIS Express settings. or webdav.
I have this controller.
public string Status([FromBody]StatusRequest p)
{
string ps= HttpContext.Current.Request["params"];
return ps;
}
It receives this post parameter value (The value is xml. Beneath is just part of it):
params=<Transaction hash=9
I get this infamous error:
A potentially dangerous Request.Form value was detected from the client
I tried a few solutions.
I tried to bind the post parameter. But there is no luck, it wont bind it so the value of 'p' is always null.
I tried setting web.config in the directory where my controller is:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpRuntime targetFramework="4.5" requestPathInvalidCharacters="?" />
<pages validateRequest="false" />
</system.web>
</configuration>
Those configurations have no effect on the files inside the directory.
Does anyone knows how to solve this?
This is really nasty exception because it reveals Server header even if you hide it so big bad guy can use that info against you.
I've found two solutions which help me. Let me explain both by using asterisk as example of dangerous symbol (but you can handle any single symbol or set of symbols in this way)
1st way is really ugly and I can't recommend it to anyone. But here it is:
Add to Global.asax.cs code
protected void Application_Error(object sender, EventArgs e)
{
if(Context.Request.RawUrl.Contains("*"))
{
Server.ClearError();
}
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
if(!Context.Request.RawUrl.Contains("*"))
{
return;
}
var newPath = Context.Request.RawUrl.Replace("*", "");
base.Context.RewritePath(newPath);
}
That's it. For any url with asterisk you'll omit this annoying exception and just replace dangerous symbol with anything you want.
2nd way is slightly trickier, but as for me, much better. Just keep in mind, that you can't use it if you don't have possibilities to install URL Rewrite module for IIS. Check next article for the details. Article is a little bit dated, if you use IIS 10 as I do, you need to get URL Rewrite module here.
So first of all you have to install this module. After that add this section to your web config file in system.webServer section:
<rewrite>
<rules>
<rule name="Rewrite URL to remove asterisk from path.">
<match url="^(.*)\*(.*)$" />
<conditions logicalGrouping="MatchAny" />
<action type="Rewrite"
url="{R:1}{R:2}" />
</rule>
</rules>
</rewrite>
That's all. Now almost any malformed url with asterisk will work without this annoying error.
Why almost? Because you'll still get exception if dangerous symbol presents in the name of, for example, IIS virtual directory.
So both ways handle errors like http://localhost/WebApplication1/api*/Values
And both ways fails with url like this http://localhost/WebApplication1*/api/Values
Just remove asterisk from requestPathInvalidCharacters under Web.config
...
<system.web>
<httpRuntime requestPathInvalidCharacters="<,>,*,%,&,:,\,?" />
...
I am creating a tool for uploading csv output files to be processed into a database. For various reasons we are automating this via powershell, and the easiest route was to create our own Cmdlet sets. This has worked really well with our smaller data sets but isn't working so hot with our larger data sets.
We have a requirement to be cross-domain when sending our data, as we can't guarantee all our machines are on the same domain, or even in a domain. Early on, this meant we went with WebClient since we had access to System.Net.NetworkCredential through it.
Format for the PS client code is straightforward:
// using Newtonsoft.Json for serializing
// ResPack resultsPackage is just a container class with some info
// plus one or more log files read in earlier
var postBody = JsonConvert.SerializeObject(resultsPackage)
response = await client.UploadStringTaskAsync(_uri, postBody);
I am using WebApi2 in an IIS8.5 (local via Win 8.1) environment to accept these files as POST and am keeping it really simple:
[HttpPost]
public async Task<ResultsPackageResponse> Post()
{
dynamic contentJson = await Request.Content.ReadAsStringAsync();
var content = JsonConvert.DeserializeObject<ResultsPackageInfo>(contentJson) as ResultsPackageInfo;
var response = new ResultsPackageResponse();
if (!string.IsNullOrEmpty(content.ClassicLogData))
{
var dataClassic = DeserializeClassicLogWithMap<ClassicLog, ClassicLogMap>(content.ClassicLogData);
response.ClassicLogResultId = ImportClassicResultsToDb(dataClassic, content.ReportSetup);
}
if (!string.IsNullOrEmpty(content.NewLogData))
{
var dataNewLog = DeserializeNewLogWithMap<ClassicLog, ClassicLogMap>(content.NewLogData);
response.NewLogResultId = ImportNewResultsToDb(dataNewLog, content.ReportSetup);
}
return response;
}
The WebApiConfig.cs is set up to use a JsonMediaTypeFormatter, because of some other tool interactions.
This works fine for smaller postBody sizes (files serialized were about 34k) but we start processing another type of log file that started throwing webResponse.StatusCode of Internal Server Error 500 (this is about 140k-800k). Realistically these aren't that large of files, so I was surprised to get errors with larger files.
I have already checked the data itself, it is valid and formatted correctly.
I have looked online for size limitations and although this doesn't sound like it meets all the problems, I have implemented these changes to my Web.Config:
<system.web>
<httpRuntime targetFramework="4.5.1" executionTimeout="240000" maxRequestLength="1073741824" />
</system.web>
<system.webServer>
<httpErrors existingResponse="PassThrough" />
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
</system.webServer>
<appSettings>
<add key="aspnet:MaxJsonDeserializerMembers" value ="1073741824"/>
</appSettings>
Nothing seems to have changed this behavior.
Resolution
I am using a formatter and this changes the game a little: JsonMediaTypeFormatter
I added this line in its constructor:
MaxDepth = int.MaxValue;
And I added this to the web.config
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="1073741824" />
</webServices>
</scripting>
</system.web.extensions>
Trying to move from OData v3 to OData v4. Why do I keep getting a 404 when trying to use OData Functions?
Web API Config:
ODataModelBuilder builder = new ODataConventionModelBuilder();
//etc
builder.EntitySet<LocalizableString>("LocalizableStringApi");
//etc
var getComparitiveTableFunction = builder.EntityType<LocalizableString>().Collection.Function("GetComparitiveTable");
getComparitiveTableFunction.Parameter<string>("cultureCode");
getComparitiveTableFunction.ReturnsCollection<ComparitiveLocalizableString>();
//etc
config.MapODataServiceRoute("OData_Kore_CMS", "odata/kore/cms", builder.GetEdmModel());
C# Code:
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
[HttpGet]
//[ODataRoute("Default.GetComparitiveTable(cultureCode={cultureCode})")] // Tried this, but gets errors and I noticed the function is in the OData model anyway without this, so should be fine.
public virtual IHttpActionResult GetComparitiveTable([FromODataUri] string cultureCode)
{
// Implementation
return Ok(query);
}
XML Returned from $metadata:
<Schema Namespace="Default">
<Function Name="GetComparitiveTable" IsBound="true">
<Parameter Name="bindingParameter" Type="Collection(Kore.Localization.Domain.LocalizableString)"/>
<Parameter Name="cultureCode" Type="Edm.String" Unicode="false"/>
<ReturnType Type="Collection(Kore.Localization.Models.ComparitiveLocalizableString)"/>
</Function>
...
As you can see, it's in the schema / OData model... yet the following query does not work:
http://localhost:30863/odata/kore/cms/LocalizableStringApi/Default.GetComparitiveTable(cultureCode='en-US')
I have also tried the following:
http://localhost:30863/odata/kore/cms/LocalizableStringApi/GetComparitiveTable(cultureCode='en-US')
http://localhost:30863/odata/kore/cms/Default.GetComparitiveTable(cultureCode='en-US')
http://localhost:30863/odata/kore/cms/GetComparitiveTable(cultureCode='en-US')
All of the above result in a 404.
So... what am I doing wrong here?
I solve a similar problem adding a trailing slash to the requested url.
I solved this by adding the following line in my web.config, under <system.webServer>:
<modules runAllManagedModulesForAllRequests="true">
This may cause performance issues though, if I remember correctly. So it's not ideal. Any better solutions are very welcome...
You need a module that goes by the name of UrlRoutingModule-4.0 to be running through IIS. This solution causes all your registered HTTP modules to run on every request, not just managed requests (e.g. .aspx). This means modules will run on ever .jpg .gif .css .html .pdf etc.
So, a better solution would be to add the following in your web.config
<modules>
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
</modules>
Source: http://www.britishdeveloper.co.uk/2010/06/dont-use-modules-runallmanagedmodulesfo.html
This is a solution to prevent 404 Not Found error with OData functions / actions.
Benefits of this solution
Works with OData URI without slash at end (example: http://domain.org/odata/Objects/ObjectService.Action)
Works with OData URI with a slash at end (example: http://domain.org/odata/Objects/ObjectService.Action/)
Doesn't cause any performance issue.
Add theses lines in your web.config
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0Custom" path="/odata*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Et VoilĂ :)
I am having quite a few problems with custom extensions and intercepting existing handlers.
What am I trying to do
Based upon persisted options, I would like all 'virtual' extensions to be handled by set handlers. All pages are dynamically built, and no actual files exist on the site. The site populates the content, forms the html output and returns it as the web result.
This is required as I am setting up a fat/thin relationship between 2 servers. The thin server will simply pass on the request to the fat server - where the request is processed and response issued back down the line.
The project is for a dynamic multi-domain content management system. The thin server may not be .net compatible (hence the external request), but will be .net optimised (hence the need for handlers).
The Problem
What I want is to re-route existing extensions - aspx; php; html.
I have achieved this in my local environment using a custom HttpModule which sets the appropriate handler. I have explored setting the tag in config, but the the extensions are re-routed using dynamic rules that are persisted.
As mentioned, this solution works on localhost.
When uploaded, the .Net extensions are handled by the module correctly but any custom extensions or non-.net extensions return a 404 error.
Seeking an alternative, I have experimented with routing within Global, but this dis not work either.
I have also attempted to use to register the custom extensions... but each are met with the same result - 404 not found.
Global Routing attempt:
public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.Add(new Route("{action}.sqs", new SqlRequestHandler()));
}
.Config (for handler and module attempt)
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpRuntime requestValidationMode="2.0" />
<customErrors mode="Off"/>
<httpHandlers>
<add path="*.sqs" verb="*" type="CmsMapper.VirtualHandler, CmsMapper" />
<add path="*.sql" verb="*" type="CmsMapper.VirtualHandler, CmsMapper" />
</httpHandlers>
<httpModules>
<add name="SisBerCMS" type="CmsMapper.VirtualModule, CmsMapper" />
</httpModules>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<modules>
<add name="SisBerCMS" type="CmsMapper.VirtualModule, CmsMapper" />
</modules>
<handlers>
<add path="*.sqs" verb="*" type="CmsMapper.VirtualHandler, CmsMapper" name="sqsHandler" />
<add path="*.sql" verb="*" type="CmsMapper.VirtualHandler, CmsMapper" name="sqlHandler" />
</handlers>
</system.webServer>
Custom Module (CmsMapper.VirtualModule)
if (extentionMap != null)
{
// note that extentionMap.ExtentionType is a predetermined enum
switch (extentionMap.ExtentionType)
{
// If the extention is banned then pass back a generic message
case ExtentionType.Banned:
this.WriteTextResponce("Invalid extention detected:" + extentionMap.Extention);
break;
// Remap .Ajax requests to the ajax handler
case ExtentionType.Ajax:
this._app.Context.RemapHandler(new AjaxHandler());
break;
// Remap session query or sql requests to the sql handler
case ExtentionType.SessionQuery:
this._app.Context.RemapHandler(new SqlRequestHandler());
break;
// if the extention is not ignored, re map to the virtual page handler
default:
bool isManagementServer = this._app.Context.Request.Url.Authority != VirtualModule.RESPONSE_SERVER;
bool isPostRequest = !String.IsNullOrEmpty(this._app.Context.Request.Form[HtmlRequest.RequestOrigin]);
bool isGetRequest = !String.IsNullOrEmpty(this._app.Context.Request.QueryString[HtmlRequest.RequestOrigin]);
bool isIgnored = extentionMap.ExtentionType == ExtentionType.Ignore;
if ((isPostRequest || isGetRequest) && !isIgnored)
{
this._app.Context.RemapHandler(new VirtualHandler());
}
else
{
this._app.Context.RemapHandler(new ExternalRequestHandler());
}
break;
}
}
All the handlers are pretty standard implementing the following:
public class SqlRequestHandler : IHttpHandler, IRequiresSessionState, IRouteHandler
Again, the preferred method - HttpModule - works on my localhost machine. This could be a server config issue (in which case I'm looking for a work around), but the fact that the .net extensions are being handled is strange - as this would imply that issues with medium trust should not apply, however issues regarding extension handling on the server may take priority over the .net application.
The server is shared hosting (therefore I am unable to alter the machine.config files), is IIS6 using 4.0.
Thank you for any suggestions on how to resolve this issue.
Mike
You need to configure web site in IIS 6.0 to route all extensions (including extensionless paths known as wildcard extension mapping) to ASP.NET ISAPI dll (and disable the check for file exists).
You can of course do this mapping selectively only for those extensions that you want to route via ASP.NET code. But wildcard mapping will be more useful in case you don't have predefined set of extensions.
In the absence of such mappings, IIS will not forward requests for unknown extensions to ASP.NET (and routing code will not even come into picture) - rather IIS will pass the extension to default (static file) handler that will issue 404 if file is not present.
See this article that describes these steps (for ASP.NET MVC but the same applies to your case): http://haacked.com/archive/2008/11/26/asp.net-mvc-on-iis-6-walkthrough.aspx
Near the end of article, author has given how to add wildcard script map