I'm using WCF to invoke a remote REST API, and am getting a 500 Internal Server Error from the service. Using Fiddler, I can see the body of the 500 response (which includes, buried in HTML, the reason for the 500 error). I would like to be able to examine the response body in .Net, but it appears that the WebFaultClientMessageInspector gets there first, and throws a vague exception.
Is there anyway to disable/override this inspector (and see the full response body)?
I think I've figured this out - I do need a custom message inspector (IClientMessageInspector), but I also need to configure it FIRST in my WCF Endpoint configuration:
<endpointBehaviors>
<behavior name="myCustomErrorWebHttp">
<myCustomnClientBehavior />
<webHttp />
</behavior>
</endpointBehaviors>
Doing THIS caused my inspector to be triggered BEFORE WebFaultClientMessageInspector, and I was able to inspect the message body.
From this link
How to solve this problem? The answer is obvious: create custom
implementation IClientMessageInspector and use it on client.
Full details is in the link.
Related
I have wsdl which was generatede by JAX-WS RI of a working web service, but i don't have access to the service itself.
Now what i would like to do is, to create my own WCF service out of the wsdl that i got. So i could just switch url's in the config file.
I created service interface with svcutil.exe.
svcutil my.wsdl my.xsd
All seemed ok until i tried to check my service via browser, i got:
The operations X and Y have the same action (). Every operation must have a unique action value.
Hmm.. ok. i checked the interface and realized that, yes, code generator has given each operation same name - "".
[System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
So i replaced all these linse with plain [OperationContract] and all seemed to work well until i tried to call my service from client. In config i just modified endpoints address.
The exception i got was: The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher
To me it seems like client is requesting operation with no name. How is it possible that working service knows which operation to use?
If i add new my service as a new service reference, all works fine.
What am i missing here?
How can i make WCF service to work on same contract it was generated from?
EDIT:
I did some more debugging. I creted opration
[OperationContract(Action = "*", ReplyAction = "*")]
public object UnknownAction()
{
return null;
}
When i add breakpoint to this operation i see from OperationContext.Current.IncomingMessageHeaders.Action that Action is empty. Message body is totally correct though.
Is there some kind of behavior i need to define on the server side?
current behavior configuration looks like this:
<behavior name="svcBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
EDIT vol2
When i create asmx web service and try to call web method from client, i get SoapException: Server did not recognize the value of HTTP Header SOAPAction: .
I am trying to set up a simple WCF REST service that we will be able to call from jquery. When I visit the URL in the browser, I get a response back. When I attempt to send an HTTPRequest directly (using the Firefox plugin RESTClient), I get a response back. These responses look correct to me, containing headers and a string of JSON and apparently nothing else.
However, when I call this same service via a jquery.get() or jquery.post() call, nothing happens. Using the jquery.ajax() call reveals the error callback gets called, but to me the data given to the error callback doesn't give me clues as to why this isn't working.
<a id="thelink" href="javascript:void(0)">GO</a>
<script type="text/javascript">
function doAjax() {
$.ajax({type: "POST",
dataType: "json", // see note below
url: "http://localhost:54459/MySimpleService.svc/json/24",
success: function(jqXHR, textStatus) {
alert("success");
},
error: function(jqXHR, textStatus, errorThrown) {
alert("error");
}
});
}
$('#thelink').click(doAjax);
</script>
Note: for the dataType parameter I have tried all of "text", "json", "jsonp" and leaving the parameter off. Similarly, I have tried with both GET and POST (modifying the web service to respond to GET or POST respectively).
The method called at that endpoint doesn't do anything spectacular that should be failing -- it simply concatenates the string to a constant and returns (just testing at this point, it will clearly do more interesting things in the future)
Firefox shows me getting back 200 OK when I click the link.
The WCF service is running out of my Visual Studio 2010 debug environment. It hits breakpoints placed in the method that responds to this service method.
I have tried accessing the html posted above from a file on my local machine (port 80) as well as hosting it elsewhere, with the same results. Could this be a security issue?
The values passed to the error callback don't seem terribly helpful:
jqXHR - readyState : 0, status : 0, statusText : error
textStatus - "error"
errorThrown - ""
So, why does my service seem to work, for GET or POST, when I call the url in a browser or RESTClient, but fail when I attempt to call it from jquery.ajax()?
EDIT: after more tests based on the comments I received, I tried hosting the page with the javascript on the same port as the web service, and this shows success. In my real-world scenarios, I won't have the luxury of hosting the client side code and the web service on the same domain/port. I'm assuming this is a security model issue -- where do I look to allow this sort of access (whitelisting domains/ports or otherwise)
The issue seemed to be in my web.config; as we worked out in comments, the issue is one of cross-domain security. I was already using a webHttpBinding on my endpoint, but did not realize it needed to be configured:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingWithJsonP" crossDomainScriptAccessEnabled="true"/>
</webHttpBinding>
</bindings>
...
</system.serviceModel>
Setting crossDomainScriptAccessEnabled="true" seems to have done the trick. Note that I already have <serviceMetadata httpGetEnabled="true"/> as part of my service behavior.
make sure you have already configured your service to be called from script clients: adding a couple of elements in web.config in your service:
<behaviors>
<endpointBehaviors>
<behavior name="webScriptEnablingBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
more info here: http://msdn.microsoft.com/en-us/library/bb763177(v=vs.90).aspx
hope it helps,
I want to send something like:
<GetColors>
<Credentials username="test" password="test" />
<GetColors>
Once I receive the request, I want to read in the Credentials, verify it. If it is verified, I will send back a soap response. How can I do this?
With build in stuff you can't. You can turn off the SOAP processing by either using REST service or custom binding with MessageVersion.None and you must build valid SOAP response manually like any other XML document.
I know there are a lot of questions out there about this - believe me I've read a lot of them and tried the answers out.
(This project is for an internal company lan, not the internet)
We have a WCF webservice which is RESTFUL and sends/receives JSON, it requires NTLM (Kerb would also be good) auth/credentials to ensure that the calling user (from the browser is who they say they are), and this is negotiated between the browser/client and the service by the WCF bindings:
<bindings>
<webHttpBinding>
<binding name="webHttpBindingAuth">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Ntlm"/>
</security>
</binding>
</webHttpBinding>
</bindings>
Using Fiddler, I can call the methods on the service GET and POST successfully and provided I adjust the JSON we're sending to the webservice (to include the session ID for example) it trundles along happily.
The problems started when we tried to use JavaScript/jQuery to call the webservice; the idea is that a web server will supply the HTML/JS to the client browser, the browser should then call the WCF webservice to get a session and allow a user to perform a few actions (we have 3 methods in total).
Firstly, we ran into the X-Domain issue, which we tried to resolve by getting the web server to return the correct headers (Access-Control-Allow-Origin). This didn't prevent browsers like SRIron from telling us that;
XMLHttpRequest cannot load http://{webServiceUri}/InstantMessagingService/chat/start/{username}. Origin http://{web**Server**Uri} is not allowed by Access-Control-Allow-Origin.
Following this, I investigated the possibility of using Silverlight (doesn't seem to support NTLM auth over WebHttpBinding), reverse proxy is out, as the IIS server being used in dev won't be used in prod (I believe it is WebSphere, but not under our control); next I looked at this:
http://msmvps.com/blogs/paulomorgado/archive/2007/04/27/wcf-building-an-http-user-agent-message-inspector.aspx
Which left me under the impression that the WCF web service was in fact the thing that needed to tell the browser where it was allowed be called from (if that makes sense). Having implemented all the code from the example, I found that the ApplyClientBehavior was never called to attempt to return the headers to the client (monitoring this in Fiddler too). Some more Googling led me to:
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/707aa031-f4ff-47ab-ba5b-730f7930605e/
Since we're accessing the web service using jQuery and not some .NET client/service reference/proxy/app.. blah, I'm thinking that it's not possible to pre-request-send these headers to allow access to the service. Also, Fiddler seems to think that it's getting a 401 Unauthorized when it does make the attempt to call the http://../chat/start/.. method.
Here's the jQuery I'm using to attempt to make the call (I supplied a few settings in the hope it was going to work):
var url = webserviceUrl + "chat/start/" + remoteUserUri;
$.ajax({
type: 'GET',
url: url,
crossDomain: true,
beforeSend: function(xhr){ xhr.withCredentials = true; },
contentType: "application/json; charset=utf-8",
success: function (data) { conversationStarted(data); },
dataType: 'json'
});
Ok, if anyone has helpful hints or ideas, please fire away. I'll reply and edit etc. to make sure this is kept up to date, I hope I haven't missed anything (but my heads spinning a little from my Googling).
Also, I know that there might be better ways to do this, but I'd like to do it in the cleanest/quickest way from where I am now - i.e. not a lot of code changes, rewrites etc. I can also post up configs if people think they really are useful.
In the end I had to kind of work around, we got the guys in charge of the web server to agree to serving up an IFrame which points to our IIS hosted page (the one containing the JS etc.)
Then using the magic of WCF/Windows we host the WCF services on port 80 which gets around the X-Domain origin stuff. So I can then have REST/JSON without having to use JSONP.
I know it's not the answer to the question given the criteria I specified, but I think I ran out of options completely in the end.
Can you use JSONP? It'll solve your cross-domain problem in a heartbeat.
How can I detect the user agent in a web service? My web service is implemented using a WCF webservice with basicHTTPBinding. It will be a post from some SOAP clients. I wish to know the user-agent from the clients.
I shall like to see some sample code for this.
I am using a WCF based web service and in the svc.cs, I tried to catch this.Context.Request.UserAgent. But it gives the following error:
this.Context.Request.UserAgent 'MySoapService.MyService' does not contain a definition for 'Context' and no extension method 'Context' accepting a first argument of type 'MySoapService.MyService' could be found (are you missing a using directive or an assembly reference?)
I also tried System.Web.HttpContext.Current.Request.UserAgent and it says:
'System.Web.HttpContext.Current' is null
Edit note:
I tried to activate the ASP.NET compatibility mode. I added <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> in the config file and added [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] on the top of the class that implements the service interface. Then using System.Web.HttpContext.Current.Request.UserAgent gives me the user agent as desired.
There is another way to get the user agent without enabling ASP.NET compatibility in web.config:
string userAgent = WebOperationContext.Current.IncomingRequest.Headers["User-Agent"];
You can use also:
WebOperationContext.Current.IncomingRequest.UserAgent
You can read user agent from the HttpContext.Current.Request object if you enable ASP.NET compatibility in web.config:
What a totally unhelpful response!
This is not a trivial task. Yes it is obviously possible to get te user-agent string but how does one actually do it? I spent 2 hours checking google and so on but found the answer buried in MSDN documentation. In Visual Studio, from within a WebMethod try
this.Context.Request.UserAgent
That should do it!
User-Agent is a standard HTTP header. It'll be available to your web service just like it's available to anything CGI-like.
Did you even bother searching for this before posting your question? There must be millions of hits for it on Google.