1

I have a WCF Rest Service and an OperationContract defined in the following way:

[ServiceContract]
public interface IMyService {

[OperationContract]
[WebInvoke( Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "get/{filename}" )]
MyFileStructure GetFile( string filename );

}

The Server stores some files and the GetFile() retrieves some information from the specified file in the GET request and put them in a MyFileStructure instance which is then JSON parsed and returned back to the client. E.g. the user can get data from the file named myfile.xml, just typing the following on the browser: http://localhost:[port]/MyService.svc/get/myfile (the file extension is always ".xml"). This works fine.

The question:

I now need to customize this request a bit more, passing some parameters to my file request. Basically, each stored XML file contains a set of attributes, which can be different (in attribute names and size) from file to file. Please notice that a domain of these attributes does not exist. Each parameter in the request should refer to a specific attribute of the specified file, but since the attributes defined in the file are not known, I cannot use the following:

[OperationContract]
[WebInvoke( Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "get/{filename}?param1={param1}" )]
MyFileStructure GetFile( string filename );

I would like to be able to pass my parameter list in a standard GET request, e.g.: http://localhost:[port]/MyService.svc/get/myfile?myparam1=value1&myparam2_value2&...

but, at the same time being able to receive that as a single string/whatever object on the server side, in order to process the parameters based on the selected file. Is that possible? How?

smn.tino
  • 2,272
  • 4
  • 32
  • 41

4 Answers4

1

You can receive a json object with any parameters you want or a key value pair object, like a dictionary, as it follows:

MyFileStructure GetFile( string filename, [FromBody]IDictionary<string, string> params);

And in javascript:

var parms = {};
parms['param1'] = "one";
parms['param2'] = "two";
$.ajax({
    url: '/api/GetFile?filename=' + filename,
    data: JSON.stringify(parms),
    contentType: 'application/json'
    type: 'POST',
    dataType: 'json'
});

Hope it helps.

Ricardo Pontual
  • 3,749
  • 3
  • 28
  • 43
  • Hi @Ricardo and thanks for your reply. It does not seem to work, it expects all path variables (filename and params in this case) to be of string type. Furthermore, [FromBody] is not recognized by VS. – smn.tino Nov 16 '15 at 16:03
  • [FromBody] is new in Web Api, my mistake, I could realize that you're using wcf without Web Api, so it will not work. – Ricardo Pontual Nov 16 '15 at 17:33
  • After googling a bit I found out this [Stackoverflow question](http://stackoverflow.com/questions/9348639/wcf-vs-asp-net-web-api) that compares WCF vs Web API in .NET. It sounds like I should use Web API: I do not have so much experience with Web API, but if I moved to Web API then would I be able to perform my call from browser as described in my full description? I guess the Javascript client you described is an example that can be executed from any client. – smn.tino Nov 17 '15 at 08:12
  • 1
    Web Api is a good option to serve restful services, easy to use from javascript. You can call from a browser as well. I think in your scenario you have another advantage: you can also pass any parameters you want as query string and recover in your method using Request object. – Ricardo Pontual Nov 17 '15 at 10:07
  • I decided to mark this as the correct answer, as it actually fixed my issue. For some (not so clear) reason, WCF does not look really flexible when developing REST web services. It seems much easier with ASP.NET Web API. Just moving from my existing WCF project to a Web API one, using the method declaration (I am using [FromUri] instead of [FromBody] as I pass parameters directly in the Uri string) suggested by @Ricardo, solved the issue. – smn.tino Nov 22 '15 at 18:28
  • 1
    You're right, when working with soap services, WCF is great, but using restful services, web api it's better and is easier to implement. – Ricardo Pontual Nov 23 '15 at 10:26
1

From the question I didn't understand if it is critical to use only GET requests or not.

But if it is, one more options could be usage of http headers. You can pass any header you want from the client, do then a GET request and then access these header in your service using weboperationcontext.current.incomingrequest.headers. You can check here if some header specified and run some specific code for it, otherwise check another header and so on.

And yes WebAPI, is a kind of symbiosis of WCF and ASP.NET which is preferably now for RESTful API development. But you can use headers there as well.

Mimas
  • 525
  • 3
  • 7
1

I think it is not a good idea to use GET Http verb for method which takes a multiple parameters as input data. In this case I would recommend to use POST Http Verb. Something like that:

[OperationContract]
[WebInvoke( Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = **WebMessageBodyStyle.WrappedRequest**,
UriTemplate = "/getFiles" )]
MyFileStructure GetFile( List<string> filenames );

It will be a little bit comfortable to use and it also has a serious advantages over sending data via Get request such as safety. If you will have a lot of parameters you may lost some of them because of max length of url (which equal to 2000 characters). Using post request you can avoid this problem

Tequila
  • 726
  • 7
  • 23
0

My best bet is use a post request to do it. You can use Stream as parameter in method and which will gain you to read and save file stream and other data also.

Lakshan Dissanayake
  • 521
  • 1
  • 4
  • 18
  • Hi @Supun and thanks for your reply. I considered that, however I need to perform that mainly via browser and getting the JSON response back, therefore I cannot see any other way of using the GET method. – smn.tino Nov 16 '15 at 16:10
  • 1
    It can be done and I've done it once. I don't remember it now. I will be able to post a reply tomorrow. – Lakshan Dissanayake Nov 16 '15 at 16:12