Suppose I implement a WCF REST service with the following contract.
[ServiceContract]
interface INotesService
{
[OperationContract]
[WebInvoke(Method = "GET",
UriTemplate = "notes/{id}")]
Note GetNote(string id);
[OperationContract]
[WebInvoke(Method = "GET",
UriTemplate = "notes")]
IEnumerable<Note> GetNotes();
}
Now, I have an HttpModule in the pipeline to do the authorization, but that code needs to know to which method the request will be dispatched. How do I find the signature of the method that will be invoked by WCF?
I think you should use IDispatchOperationSelector.
See also this article: WCF Extensibility – Operation Selectors
Even though the other answer put me on the right path, it did not really answer my question.
I later found this link which gave me a working solution:
http://tech.blog.oceg.org/2009/04/authorizing-rest-calls-in-wcf.html
However, I found it to be more complex than needed. In .NET 4.5 (which is what I'm on) you can do the following.
I registered my ServiceAuthorizationManager from the ServiceHost.ApplyConfiguration override.
this.Authorization.ServiceAuthorizationManager =
new MyServiceAuthorizationManager();
Then, in its CheckAccessCore method, I called the method below to give me the name of the method to which the request will be dispatched.
private string GetOperationName(OperationContext operationContext)
{
return messageProperties["HttpOperationName"] as string;
}
Related
I need the base-URI ( or of the resource) which actually triggers this Operation to include it in the response.
[WebInvoke(Method = "GET", UriTemplate = "users/user",BodyStyle=WebMessageBodyStyle.WrappedRequest)]
[OperationContract]
public bool ReadUserAccount(User user,int TaskID, **string baseURL**)
{
//do something - Include further subsequent Resource Urls with help of Base URL
return result;
}
Understood the operation Context of the WCF Framework.
OperationContext.Current.RequestContext.RequestMessage.Headers.To
reads the URL inside a Service Implementation.
I would like to make all the methods I am adding to my WCF service have the following behaviour:
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Wrapped)]
Instead of having to add these attributes to every single [OperationContract] method is there a way I can configure this service wide?
I have a stock WCF Rest application (default Web.config, Web Routing). I am unable to get the WCF framework to auto de-serialize the request stream into typed objects. I have a service with a method sig in the form...
[WebInvoke(Method = "POST",
UriTemplate = "",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json)]
MethodA(FirstParam first, SecondParam second)
If I initiate a request from fiddler or jQuery using $.ajax I get a 400 Bad Request error. I've done plenty of searching and found that changing the method sig to use a System.IO.Stream allows the method to be executed, however it also adds the overhead of de-serializing the objects.
The raw request body is as follows
{
"first":"{\"p1\":\"p1 value\",\"p2\":\"p2 value\",\"p3\":100\"p4\":null}",
"second":"{\"p1\":\"p1 value\"}"
}
Yeh the application doesn't even break into the service itself unless the method has either a Stream, or no arguments. There is only 1 post method in this service, the other is a GET method which is working correctly.
I've used http://www.codeproject.com/KB/ajax/jQueryWCFRest.aspx as a reference implementation, but have been unable to get it to work on this solution.
Is there something that I'm missing here that hopefully someone else can see?
Leon
Bleh... the problem turned out to be the way the request was serializing values!
{
"first":"{\"p1\":\"p1 value\",\"p2\":\"p2 value\",\"p3\":100\"p4\":null}",
"second":"{\"p1\":\"p1 value\"}"
}
Should have been without the escaped quotes....
{
"first":"{"p1":"p1 value","p2":"p2 value","p3":100"p4":null}",
"second":"{"p1":"p1 value"}"
}
The reason this was happening was JSON.stringify was being called not only on the wrapped request parameters, but on each parameter as well.
I am trying to create a simple non-RESTful JSON service using WCF and .NET 4.
I'd like my service to be able to parse a JSON request message with a specific format, something like this:
{ "MethodNameRequest": { "MethodParam1Name": "ParamValue1", "MethodParam2Name": "ParamValue2" } }
The endpoint for this service should reside in a single constant URI ("http://myserver/myservice/") so that all methods could be invoked using a POST request to it.
The problem is that whenever I try to declare two (or more) methods using the same "UriTemplate" and the same HTTP verb "POST" (using WebInvokeAttribute), like this:
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json, Method = "POST", UriTemplate = "")]
public string Method1()
{
return "Method1";
}
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json, Method = "POST", UriTemplate = "")]
public string Method2()
{
return "Method2";
}
I get the following exception:
In contract '', there are multiple
operations with Method 'POST' and a
UriTemplate that is equivalent to ''.
Each operation requires a unique
combination of UriTemplate and Method
to unambiguously dispatch messages.
Use WebGetAttribute or
WebInvokeAttribute to alter the
UriTemplate and Method values of an
operation.
Any ideas on how I can configure WCF to allow this?
I don't see how WCF could figure out which method to call if it somehow allowed the identical UriTemplate for the different methods. Seems you need to implement logic inside the method to handle content based processing.
Try to ommit the UriTemplate property, use instead the <enableWebScript/> element in web.config. This will allow wcf to automatically handle the requests for you.
I am writing a .NET app that will talk to JSON-based API to pull/push data. I saw similar question asked before:
Consuming a RESTful JSON API using WCF
but I need little more information on the same subject. Here is JSON that I have to send in request:
{"login":{"password":"PASSWORD","username":"USERNAME"}}
and response JSON will be something like:
{"response":{"status":"OK","token":"o9b0jrng273hn0"}}
Here is what I came up with:
[ServiceContract]
public interface ITestApi
{
[OperationContract]
[WebInvoke( Method = "POST",
BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/login"
)]
LoginResponse Login( LoginRequest login );
}
where LoginRequest has username and password properties and LoginResponse has token property.
When I call the api, request is successful and I get the response back as expected ( I verified this with Fiddler). But WCF is not able to create LoginResponse object for me. it is always null. I believe I am doing somethign wrong, can someone please point me out what I have to do to get this right?
Is this the right way to create a JSON-based REST service client? I am using RESTful api first time, so I do not have more knowledge about it.
Your LoginResponse class should look like something this:
[DataContract]
public class LoginResponse
{
[DataMember]
public string token { get; set; }
}
It needs to be decorated with the DataContract and DataMember attributes so the serializer (DataContractJsonSerializer in the case of JSON ) knows how to serialize it.
EDIT:
Also, your client should be configured to use webHttpBinding and the endpoint behavior should be configured to use webHttp, as in the following example.
Go get the Microsoft.Http client library from the lib folder in this project or from thw WCF REST Starter Kit. Using this you can do:
var client = new HttpClient();
var content = HttpContent.Create("{'login':{'password':'PASSWORD','username':'USERNAME'}}", "application/json");
var response = client.Post("http://service.com/login",content);
var jsonString = response.Content.ReadAsString();
If you don't want to read the Json as a string and parse using something like Json.Net, and you prefer to use DataContracts, you can do:
var loginResponse = response.Content.ReadAsJsonDataContract<LoginResponse>();
Using WCF Channels on the client to deal with REST services is just going cause you far more pain than you really want. You are much better to just stick with plain HTTP.