I have a standard asmx service on which GET is not allowed.
If I visit the asmx http://mysite/myservice.asmx/myoperation in the browser (GET) I get a stack trace flushed to the client and I can see from fiddler it's a 500 internal system error. None of my code is being hit.
I have a requirement not to show a stack trace if the url is visited from the browser, so I'd like to redirect to a custom error page I have in place.
I have an Application_Error on the global.asax but its not kicking in in this particular instance.
Any help appreciated!
What happens if you disable GET requests via
<configuration>
<system.web>
<webServices>
<protocols>
<remove name="HttpPost"/>
<remove name="HttpGet"/>
<remove name="Documentation"/>
</protocols>
</webServices>
</system.web>
</configuration>
Related
On 64-bit Windows 10 and IIS 10, I am trying to develop and test a native HTTP module that will act as a WebSockets handler mapping for a specific set of script files. This is all in native C++ starting with RegisterModule(). I am not using any part of ASP.NET.
When I access a URL that should invoke the handler, I receive this response:
HTTP Error 500.21 - Internal Server Error
Handler "QuadooWebSocket" has a bad module "WebSocketModule" in its module list
Detailed Error Information:
Module IIS Web Core
Notification ExecuteRequestHandler
Handler QuadooWebSocket
Error Code 0x8007000d
More Information:
IIS core does not recognize the module.
I used the IIS Manager to setup the handler mapping, and it created an entry in the applicationHost.config file.
<handlers accessPolicy="Read, Script">
<other_modules />
<add name="QuadooWebSocket" path="*.qws" verb="*" modules="WebSocketModule" scriptProcessor="E:\dev\projects\trunk\target\debug\ActiveQuadoo.dll" resourceType="File" preCondition="bitness32" />
</handlers>
Before that, I installed support for WebSockets using the "Windows Features" control panel, and it also added a line to the applicationHost.config file.
<globalModules>
<other_modules />
<add name="WebSocketModule" image="%windir%\System32\inetsrv\iiswsock.dll" />
</globalModules>
When I attach Visual Studio to w3wp.exe, none of the breakpoints in my code are resolved. RegisterModule() is not being called. DllMain() isn't even being called. My module also implements IActiveScript, and IIS does load my module for classic ASP requests.
My code is being built into a 32-bit module, and I have enable32BitAppOnWin64="true" in the applicationHost.config file. This works for the Classic ActiveScript/ASP environment, but does this setting also work when using code that is expected to be loaded via the RegisterModule() export? If that's not the issue, then are there other steps needed to enable a native HTTP module for WebSockets?
Thanks!
After nearly two years, I decided to spend the past few days working on this again, and it's finally working!
To answer the 32-bit question... Yes, IIS can run a 32-bit WebSockets handler on a 64-bit OS.
As to why it's working now... I did rerun APPCMD.EXE again, and I poked around in the configuration until it looked like this:
<globalModules>
...
<add name="WebSocketModule" image="%windir%\System32\inetsrv\iiswsock.dll" />
<add name="WebSocketModule32" image="%windir%\SysWOW64\inetsrv\iiswsock.dll" />
<add name="QuadooWebSocket" image="E:\dev\projects\trunk\target\debug\ActiveQuadoo.dll" />
</globalModules>
<handlers accessPolicy="Read, Script">
...
<add name="QuadooWebSocket" path="*.qws" verb="*" modules="WebSocketModule32" scriptProcessor="E:\dev\projects\trunk\target\debug\ActiveQuadoo.dll" resourceType="File" preCondition="bitness32" />
...
</handlers>
<location path="Default Web Site">
<system.webServer>
<handlers>
<remove name="QuadooWebSocket" />
<add name="QuadooWebSocket" path="*.qws" verb="*" modules="QuadooWebSocket" scriptProcessor="E:\dev\projects\trunk\target\debug\ActiveQuadoo.dll" resourceType="File" requireAccess="Script" preCondition="bitness32" />
</handlers>
</system.webServer>
</location>
One difference is that my handler is now registered with the WebSocketModule32 module.
I could end the answer there, but after my handler was finally loaded, there were a number of issues that I had to work out before it actually worked correctly. Some of what I've learned might be useful to others.
Since I'm handling WebSockets asynchronously, I needed to return RQ_NOTIFICATION_PENDING from OnExecuteRequestHandler(). Otherwise, IIS immediately closed the connection.
When switching to WebSockets, this was the order I ended up using:
Set the module context.
Set the response status to 101.
Load my script VM.
Write headers (e.g. Sec-WebSocket-Protocol).
Flush() asynchronously.
If Flush() does not complete immediately, then it will be completed with a call to OnAsyncCompletion(). If it does complete immediately, use the same code path that would be called from OnAsyncCompletion() and do the following:
Get the named context for IIS_WEBSOCKET.
Cast the context to an IWebSocketContext pointer.
Start the asynchronous reader loop.
Return RQ_NOTIFICATION_PENDING.
After receiving the closing event from ReadFragment(), I call IndicateCompletion(RQ_NOTIFICATION_FINISH_REQUEST) to notify IIS that I am done with the connection. Before I added that, IIS wasn't calling my handler's CleanupStoredContext() method.
I have an ASP.NET Core 2.0 API that I am trying to debug using VS2017 / IIS Express on my local Win10 dev computer and I am running into an issue with IIS Express in that it is hitting the response timeout default of 2 minutes before my process can complete in my API, thus returning a 502.3 - Bad Gateway message.
I process continues to run in my API and completes after 3 minutes and 50 seconds. So, I need to increase the request timeout for IIS Express.
Most of the examples I have found on the web talk about using the web.config, for example;
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore requestTimeout="00:20:00" processPath="dotnet" arguments=".\MyAPI.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
</system.webServer>
</configuration>
... but from what I understand, An ASP.NET Core 2.0 API running on the local IIS Express doesn't uses a web.config from my project bt rather, it relies on launchSettings.json in the project. However, I have not been able to find anything on the web that talks about launchSettings having any settings values for increasing default timeouts.
Just to confirm, I tried putting a web.config file, like what I listed above, in my project's wwwroot folder, but it made no difference. This worked on my deployed solution in Azure (see related Stack Overflow post) but doesn't in IIS Express on my local dev.
This seems like it should be a simple task but so far I have not had any luck finding a solution.
Any ideas?
EDIT 5/27/18 - SOLUTION
IIS Express with ASP.NET Core 2.0 uses a file similar to a web.config called applicationhost.config, which is located in the project root/.vs/config folder. This file has a
<configuration><Location> ... <location</configuration>
section similar to what I have listed below. This section has the
<aspNetCore ... />
node where I was able to apply the requestTimeout value. By setting that, my dev system was able to get past the default 2 minute timeout.
<location path="MyAPI">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<httpCompression>
<dynamicCompression>
<add mimeType="text/event-stream" enabled="false" />
</dynamicCompression>
</httpCompression>
<aspNetCore requestTimeout="00:20:00" processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" forwardWindowsAuthToken="false" stdoutLogEnabled="false" />
</system.webServer>
</location>
You misunderstood the concepts.
launchSettings.json is only used by Visual Studio to determine how to run your web project. (More info in my blog post)
IIS Express still relies on web.config to read the settings, as that's the only file it understands.
Note: I could not find a straight-forward answer to this problem so I will document my solution below as an answer.
I generated the server-side part of a webservice from a wsdl using Axis 1.4 and
the axistools-maven-plugin. The Axis servlet is mapped to /services/*, the
service is configured in WEB-INF/server-config.wsdd as follows:
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="TestService" style="document" use="literal">
<namespace>http://example.com/testservier</namespace>
<parameter name="className" value="com.example.TestServiceImpl"/>
<parameter name="allowedMethods" value="*"/>
<parameter name="scope" value="Session"/>
</service>
</deployment>
When I deploy this web application to Tomcat and access
http://localhost:8080/testservice/services a list of deployed services is
returned.
And now... Some Services
TestService (wsdl)
TestService
Clicking on wsdl should return the description for this service but results in the following error page:
AXIS error
Could not generate WSDL!
There is no SOAP service at this location
The server-config.wsdd was missing a neccessary configuration setting.
<transport name="http">
<requestFlow>
<handler type="java:org.apache.axis.handlers.http.URLMapper"/>
</requestFlow>
</transport>
It seems the URLMapper is responsible for extracting the service name from
the url, without it axis does not know which service to invoke. This is sort of
documented in the axis faq:
This mechanism works because the HTTP transport in Axis has the URLMapper (org.apache.axis.handlers.http.URLMapper) Handler deployed on the request chain. The URLMapper takes the incoming URL, extracts the last part of it as the service name, and attempts to look up a service by that name in the current EngineConfiguration.
Similarly you could deploy the HTTPActionHandler to dispatch via the SOAPAction HTTP header. You can also feel free to set the service in your own custom way - for instance, if you have a transport which funnels all messages through a single service, you can just set the service in the MessageContext before your transport calls the AxisEngine
This makes it sound like the URLMapper would be configued by default which does not seem to be the case.
When I had this problem, it was caused by using the wrong URL.
I used http://localhost:8080/axis/services/AdminWebService?wsdl instead of http://localhost:8080/axis/services/AdminService?wsdl.
AdminWebService must be changed to AdminService.
You better build the server-config.wsdd automatically with the goal "admin". See the documentation about this plugin:
http://mojo.codehaus.org/axistools-maven-plugin/admin-mojo.html
It is very difficult to generate the server-config.wsdd manually.
Example:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>axistools-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<filename>${project.artifactId}.wsdl</filename>
<namespace>http://server.ws.xxx</namespace>
<namespaceImpl>http://server.ws.xxx</namespaceImpl>
<classOfPortType>XXXWebService</classOfPortType>
<location>http://localhost:8080/XX/services/XXXWebService</location>
<bindingName>XXServiceSoapBinding</bindingName>
<style>WRAPPED</style>
<use>literal</use>
<inputFiles>
<inputFile>${basedir}\src\main\webapp\WEB-INF\xxxx\deploy.wsdd</inputFile>
<inputFile>${basedir}\src\main\webapp\WEB-INF\xxxx\deploy.wsdd</inputFile>
</inputFiles>
<isServerConfig>true</isServerConfig>
<extraClasses></extraClasses>
</configuration>
<executions>
<execution>
<goals>
<goal>java2wsdl</goal>
<goal>admin</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>axis</groupId>
<artifactId>axis</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
I had the same problem recently.
Solution :
In my case, I was using Axis 1.4 and was deploying the application on tomcat. However, for some reason the generated server-config.wsdd was not getting packaged in the war and hence was not getting deployed on tomcat. Once, I ensured this is happening, it started working fine for me.
you ensure server-config.wsdd in your package, you can put this file to resources or you can set in your pom.xml via maven which files will be in the package
server-config.wsdd must be valid and correct tags or necessary config is exist so below rows must be in it;
<handler type="java:org.apache.axis.handlers.http.URLMapper" name="URLMapper"/>
<handler type="java:org.apache.axis.transport.local.LocalResponder" name="LocalResponder" />
<transport name="http">
<parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler" />
<parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler" />
<parameter name="qs:wsdl" value="org.apache.axis.transport.http.QSWSDLHandler" />
<requestFlow>
<handler type="URLMapper" />
<handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler" />
</requestFlow>
</transport>
<transport name="local">
<responseFlow>
<handler type="LocalResponder" />
</responseFlow>
</transport>
I want to check raw data string (raw xml) received by my web service methods (for logging and debugging purposes).
I saw recommendations: to handle 'BeginRequest' event in HttpApplication. But I don't see which field of 'Request' object contains this POST data?
Related question: Getting RAW Soap Data from a Web Reference Client running in ASP.net
- Have you seen this answer using tracing? or this one using a SoapExtension
I made following changes in web.cofig
to get SOAP(Request/Response)
Envelope. It makes trace.log file
where all the required information are
present
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="System.Net" maxdatasize="1024">
<listeners>
<add name="TraceFile"/>
</listeners>
</source>
<source name="System.Net.Sockets" maxdatasize="1024">
<listeners>
<add name="TraceFile"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="trace.log"/>
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Sockets" value="Verbose"/>
</switches>
It would not make sense to keep all the request post data in the request object since it could contain uploaded file and be very big.
I have two solutions for you:
1) Use Fiddler on the server and browse locally the website (using server name and not localhost since Fiddler cannot show localhost request/responses)
2) Use System.Net tracing: http://support.microsoft.com/kb/947285
You can also use WireShark to look at the packets but this will not keep the request response context.
I have tried to implement progress reporting using a soap extension as described at the following links:
stackoverflow
codeproject
However, my "ProgressUpdate" method is not being called, and I believe that is because I haven't got an app.config file in my Windows Mobile project to tell the web service calls to be processed by the SOAP Extension. How can do it in Windows Mobile? This is the sample config file used in the article:
<?xmlversion="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<webServices>
<soapExtensionTypes> <add
type="SoapExtensionLib.ProgressExtension, SoapExtensionLib"
priority="1" group="High" />
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>
I figured out how to do this by adding a custom attribute to the method inside the generated proxy class. The custom attribute is derived from SoapExtensionAttribute.
I got the information at MSDN
Problem now is that I have to remember to add the attribute back in if I refresh the web service reference..............