Does a .net 2.0 web service always use Soap over http? - c#

Im doing research and I downloaded a test app that calls a standard .asmx service. The service is being called using a standard POST request. Im slightly confused because I thought .asmx services always used SOAP? Or is the ability to communicate with HTTP (POST) something that was introduced recently?

.NET Web-Services uses the one protocol you choose. By deafult it is the SOAP, and POST requests are allowed.
Standart help page automatically created by .NET:
POST /demo/MSDN/PerfCounter.asmx HTTP/1.1
Connection: Keep-Alive
Content-Length: 150
Content-Type: text/xml
Host: localhost
User-Agent: MS Web Services Client Protocol 1.0.2204.19
SOAPAction: "http://tempuri.org/PerfCounters"
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<soap:Body>
<PerfCounters xmlns="http://tempuri.org/"/>
</soap:Body>
</soap:Envelope>
Also you can enable the GET method:
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>
This works from .NET 1.1

No, ASMX webservices are not limited to SOAP. You can use the ScriptMethodAttribute to specify the a HTTP verb for a webmethod. This was introduced in .Net 3.5. For example:
[ScriptMethod(UseHttpGet = true)]
public string MyMethod()
{
return "Hello World";
}

SOAP is a standard that you may choose to use. It's based on XML. If it's something simple, than I'd use JSON. Web services are not limited to POST. You should be using POST when you run Create/Update/Delete routines and you should use GET when you run data retrieval routines.

Related

How can I control the HTTP response headers added to my ASP.NET core web application when hosted in Azure app service?

we have written an ASP.NET core 2.2 web application which basically exposes a few web api controllers and we have used the ResponseCachingMiddleware in order to implement a server side response cache in our middleware pipeline.
We followed this Microsoft guide and we decided to add the HTTP response header Vary so that each response from our application includes the following header: Vary: Accept-Encoding, Accept-Charset.
Doing so, as explained in the guide linked above, is needed in order for the response cache to honor the client request headers so that the cached responses are used if and only if they are compatible with the client request.
Testing with postman I noticed that, when deploying the app in Azure (we used a standard Azure App Service to do so), the Vary response header is not what I would expect: it seems that Azure itself adds the value Accept-Encoding so that the value for the Vary header is set as Accept-Encoding, Accept-Charset,Accept-Encoding (this is a combination of the value set by our application and the value that, I suppose, is automatically added by Azure).
That said I have a couple of questions:
is the extra value Accept-Encoding really added by the azure host ?
is there a way to customize the HTTP headers added by the Azure host (if any) ?
is the value Accept-Encoding, Accept-Charset,Accept-Encoding a valid value for the Vary header ? is it going to work as expected even if we have a value repeated twice ?
Hosting ASP .NET Core on Azure App Service (a Windows one) still uses IIS as outlined here. So you should be able to control your headers by adding web.config to your project.
Here is an example of what that would look like and the link to the docs,
<configuration>
<system.web>
<httpRuntime enableVersionHeader="false" /> <!-- Removes ASP.NET version header. Not needed for Ghost running in iisnode -->
</system.web>
<system.webServer>
<security>
<requestFiltering removeServerHeader="true" /> <!-- Removes Server header in IIS10 or later and also in Azure Web Apps -->
</security>
<httpProtocol>
<customHeaders>
<clear /> <!-- Gets rid of the other unwanted headers -->
<add name="X-Frame-Options" value="SAMEORIGIN" />
</customHeaders>
<redirectHeaders>
<clear />
</redirectHeaders>
</httpProtocol>

WCF Client Message Format c#

I'm creating an application that consumes a WCF web service. When I test a certain operation in SOAP UI, it works, however, when I test in VS2017 console app, I receive an error:
"The content type text/html;charset=UTF-8 of the response message does not match the content type of the binding"
I used Fiddler to grab the request from my console app, and I've narrowed the issue down to some of the formatting in the SOAP request. When I format my console app request to match the request Fiddler generates, it works. There are prefixes that are defaulted in my request that seem to be causing the issue, as well as xmlns declarations. I need to know how I can modify these parts of the request to conform to the web service which I have absolutely no control over (major corporation).
The prefixes s and h need to change to different values. I took this request and put it into SOAP UI, swapped the s and h throughout to match how Fiddler is passing in the request, and it works. I also had to move xmlns:h up to the Envelope level. Is there something I can change in my config file? Is there something with Message Contracting that I can easily implement? I need to be able to format this correctly, but I'm not sure what the best way would be.
BAD:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:FooListHeader xmlns:h="http://foo.foo.com/Hello" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<h:FooList>
<h:FooStatement>
<h:Title>Foo</h:Title>
<h:Value>123</h:Value>
</h:FooStatement>
</h:FooList>
</h:FooListHeader>
</s:Header>
<s:Body>
<GetFooRequestType xmlns="http://foo.foo.com/Hello">
<MessageRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ConFooRequest/>
</MessageRequest>
</GetFooRequestType>
</s:Body>
</s:Envelope>
GOOD (how can I convert above bad example to this good example below in my app?):
<soapenv:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:foo="http://foo.foo.com/Hello">
<soapenv:Header>
<foo:FooListHeader xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<foo:FooList>
<foo:FooStatement>
<foo:Title>Foo</foo:Title>
<foo:Value>123</foo:Value>
</foo:FooStatement>
</foo:FooList>
</foo:FooListHeader>
</soapenv:Header>
<soapenv:Body>
<foo:GetFooRequestType xmlns="http://foo.foo.com/Hello">
<foo:MessageRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<foo:ConFooRequest/>
</foo:MessageRequest>
</foo:GetFooRequestType>
</soapenv:Body>
</soapenv:Envelope>
Service Reference Image
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="foo" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://Foo.foo.com/foo/foows.svc"
binding="basicHttpBinding" bindingConfiguration="foo"
contract="Service1Reference.IFooServices" name="foo" />
</client>
</system.serviceModel>
</configuration>
Everything I can find on the internet about this topic mostly revolves around the service side of things, not the client side.
The company has provided me with a .wsdl file and an XML reference file. I'm not quite sure what to do with the reference file, but I have loaded the .wsdl file directly under "Add Service Reference" in my application. I could not discover the service using the endpoint like I have in previous projects that I have worked on, so I had to store the file locally on my PC and specify the path to it directly when I added the service reference. Again, I am not able to discover the service using the typical ?wsdl address most likely due to service config settings for security purposes. Thanks so much for any responses!

RESTful WebService CORS Preflight Channel did not succeed

I created a WebService in C#. All GET methods are working without any problems.
Now I need to provide some POST methods. When calling it via C# it works without any problems. Then I tried to write a small html page with JavaScript to call my methods. But there I get a CORS error ("Preflight channel did not succeed").
I already added the following part to my web.config file:
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="*" />
<add name="Access-Control-Allow-Methods" value="*" />
</customHeaders>
Sadly it is still not working. What am I doing wrong?
So what you have here is not really a valid way to handle CORS requests. The problem is that this will add the CORS headers to all responses, but browsers will use an OPTIONS request in order to check for CORS headers. This would work if you also implement OPTIONS requests for all of your API end points.
The better option is to use one of the CORS frameworks, such as this one: Enabling Cross-Origin Requests in ASP.NET Web API 2 for ASP.NET WebAPI 2. This type of framework will intercept the OPTIONS request for you and supply the appropriate response without the need for you to manually create 2 routes per endpoint.

How to debug/trace System.Web.Services.Protocols.SoapHttpClientProtocol.invoke (from Windows mobile)?

I am trying to call web service from C# application but I am getting exception:
InvalidOperationException
client found response content type of 'text/html; charset=utf-8', but expected 'text/xml'
How can I see the request and reponse messages un URL? My service runs on Desktop, but client runs on Windows Mobile CE 6.x, mobile device is connected to the Dektop using usb. Probabily that is the reason why I don't see the HTTP traffic in Wireshark or Fiddler (I have tried both). The service works - I can check it using Postman (method returns correct and meaningful result XML).
You can turn on the debug on some of the libraries that internally make the HTTP calls (in my case, they are HTTPS, so inspecting via wireshark is impossible).
You should add to your app.config:
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="System.Net" tracemode="protocolonly" 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"/>
</switches>
</system.diagnostics>
This will add a trace.log where your exe runs. If you don't know where your service is running, you should be able to put a non-relative path.
Also, this adds the same logs when running the code inside Visual Studio, in the output window (not the output console).
P.S.: You can change the log level to "Information" if you just need the headers of the request and responses and information on opening and closing connection.
Okay, this is going to sound weird, but are you using Default Document within IIS? I know this probably shouldn't be the case, but when I set up a default document for my web service's site, and pointed my ServiceReference to the shortened address, it was able to run... but only locally. Otherwise, I'd get that same "Html instead of XML" error.
The fix in my case was to no longer refer to the shortened URL in the service reference, and type out the full URL (aka, not using the default document property for the site.)
The easiest and best way to debug a SOAP client is to create a SOAP extension that logs the SOAP messages sent to and from a Web service or Web service client.
Codeproject has a good tutorial how to do this properly: Efficient Tracing Using SOAP Extensions in .NET
And here is a shorter MSDN article: How to: Implement a SOAP Extension
There are also commercial SOAP Debuggers out that are worth the money, like the XML Spy SOAP Debugger or SOAPSonar which does validation and invocation.
BTW: If you would use PHP or Java you would basically use the same approach.

Web-service technologies cross domain

Recently I've been trying to implement a web service. I started off trying to use the "Web API" technology in C#.
The end goal is to have a web service that connects to a SQL-Server database and can be called by other sites, sat on different domains.
The web service takes the request, connects to the database and serves back HTML (can be as a string inside a JSON object...etc). The client site then displays this HTML, gets input from the user and then sends this data back to the web service to save in the database.
There seems to be a problem with "Web API" when the calls are cross domain. The same-origin policy prevents us calling Cross-Domain. I have read into CORS, but believe it is not compatible with IE8, which is a big blocker for us.
Most of my knowledge and all of our sites are ASP.net C#.
Does anybody have any suggestions on how this can be achieved?
Thanks.
I haven't use Web API , but to allow cross domain calls to web service you may try adding it to the web.config file.It will allow HTTP GET / POST requests
<configuration>
<system.web>
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>
SAMPLE REQUEST:
$.ajax({
url: "http://yoururl",
type: "GET",
data: "yourdata",
dataType: "jsonp",
success: function (response) {
//do something;
}
});
We've resolved our issue by using a WCF service.

Categories