Being completely new to WCF, I'm trying to make a RESTful service which will accept a file (the file is usually text with comma/tab-separated values) and a delimiter as parameters, parse the file and do some calculations. Based on what I read in others posts, I assume that the WCF service needs to save the file on the server first.
EDIT: I presume the answer is something similar to the one answered here, but I'm also interested in the code not mentioned in the answer.
Here is the interface method:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "dataSets/{dataSet}/metadata?delimiter={delimiter}&format=json",
BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
void PostMetadataJSON(Stream dataSet, char delimiter)
{
}
And here is the method in the class implementing the interface:
void IMyService.PostMetadataJSON(Stream data, char delimiter)
{
//the delimiter is needed for splitting each line of the file
}
Can someone explain the approach to follow? I've found some examples on SO but they only got me more confused as I am completely new to this.
Just use WCF's streaming support
http://msdn.microsoft.com/en-us/library/ms733742.aspx
Related
1) i never design or develop any wcf service with rest approach. so when i was going through lots of article of similar kind then i notice one keyword that is UriTemplate.
so like to know what is UriTemplate and what it does ?
i have seen few different kind of UriTemplate as follows below
UriTemplate = "/X/{y}?Z={z}")
UriTemplate = "/GetPeople"
UriTemplate = "/GetPerson?id={id}"
UriTemplate = "Auth/Login"
what does it mean /X/{y}?Z={z} or GetPerson?id={id} ??
what does this mean UriTemplate = "Auth/Login" when method name is AuthLogin
[WebInvoke(Method = "POST", UriTemplate = "Auth/Login", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
public bool AuthLogin(string userName, string password)
{
var provider = (SqlMembershipProvider)Membership.Provider;
if (provider.ValidateUser(userName, password))
{
FormsAuthentication.SetAuthCookie(userName, true);
return true;
}
return false;
}
2) what is AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] and what it does or confirm.
if some one do not use it then what may happen?
URITemplate is used to control the template based generation of WCF REST Service URIs. To enable customization of the URI for each method and verb combination, WCF added the ability to define the URI for each resource by using a special template syntax. This syntax allows you to define, with replaceable tokens, the URI structure you'd like each method to represent in conjunction with the HTTP verb.
The following article provides a good overview:
http://debugmode.net/2010/06/02/urirest1/
Regarding the second question about AspNetCompatibilityRequirements, the following StackOverflow post seems to provide good details:
Why does AspNetCompatibilityRequirementsMode.Allowed fix this error?
I am trying to create a wcf rest service using visual studio 2012 and .net framework 4.5.
The service will try to upload a file together with 4 or more parameters. I want to do this in only one call. I want to use the http "put" method. But I keep having these 2 errors.
Operation 'AddFile' in contract 'IRestBasketService' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body.
(When I am using BodyStyle wrapped)
and
Operation 'AddFile' of contract 'IRestBasketService' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped.
(When I am using BodyStyle bare)
What should I do ?
Bellow are the 2 signatures giving me the errors
[WebInvoke(Method = "PUT",
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "AddFile?key={key}&email={email}&fileName={fileName}&groupID={groupID}&ID={objectID}")]
Response AddFile(string key, string email, string fileName, string type, string objectID, string groupID, Stream fileStream );
[WebInvoke(Method = "PUT",
BodyStyle = WebMessageBodyStyle.Wrapped,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json,
UriTemplate = "/AddFile")]
Response AddFile(AddFileRequest request, Stream FileStream);
I'm using the webHttpBinding and the webHttp behaviour in the web.config.
Since you're using Stream as one of the input parameter, there can be no other parameters in the body. You would need to add all the extra data as part of the stream in the client and then parse it in the service.
1. Similar problem
2. Similar problem
I created a WCF service, that returns some data and also allow to post some data to.
The methods of the service are as below:
[OperationContract]
bool UploadStream(Guid key, List<StreamRecord> values);
[OperationContract]
bool RegisterStream(Guid key);
[OperationContract]
StreamCollection GetStreams(Guid key);
I need to implement this with a REST interface.
I created a new interface, IRestService as below
[WebInvoke(
Method = "GET",
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "/bitpool/{poolKey}/streams")]
BitStreamCollection GetBitStreams(string poolKey);
and it works ok (I can test it from the browser address bar and all is fine)
Now I want to implement also the Upload method, but I'm not sure how to do it
I tried with
[WebInvoke(
Method = "POST",
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "/stream/{streamKey}/records/{values}")]
bool UploadStream(string streamKey, List<StreamRecordEntity> values);
But when I try to access the service in browser it gives error
http://localhost:6767/RestServer.svc/
it gives an error:
Operation 'UploadBitStream' in contract 'IRestServerJson' has a path variable named 'values' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'.
I think for POST I cannot define such URL, but how should I do it?
Also, method RegisterStream should check if stream with key exists and if not, create it and return true, otherwise return false.
Should I define it as GET (since it must return result) or as PUT or POST?
Thanks
Pass the values in the body of the POST request, formatted in xml, not on the url. An easy way to test this is to use Fiddler.
Regarding RegisterStream, both POST and PUT can return information in the response body. You could use POST and return an appropriate HTTP status code depending on the action taken by the server: 201 Created if the resource is created, a different status code that makes sense in your application if the resource already exists.
The caller can determine whether the resource was created or already existed based on the HTTP status code returned, so the bool return value wouldn't be needed.
Side note: you can use the [WebGet(...)] instead of [WebInvoke(Method = "GET"...)].
When should use post vs get? in a REST service on WCF?, below is my interface
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]
string DoLodge(string Id, Lodge value);
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]
LodgeLevel[] GetLodgeLevels(string Id);
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]
long GetLodgeCount(string Id);
POST should be used when sending an update back to the server.
GET should be used when retrieving an object from the server.
You might want to read up on what the HTTP Verbs mean in the context of RESTful services:
http://swdeveloper.wordpress.com/2012/03/04/rest-for-the-rest-of-us/
http://homepages.tig.com.au/~ijoyner/Ian_Joyner/REST.html
POST everytime you are modifying some state on the server like database update, delete. GET for readonly fetching like database select.
GET: Get a collection of entries (as a feed document) or a single entry (as an entry document).
POST: Create a new entry from an entry document.
PUT: Update an existing entry with an entry document.
DELETE: Remove an entry.
But in C#, you receive a response in GET.
so the complete answer will be,
GET should be used when retrieving an object from the server and used when sending an update back from the server.
This question already has answers here:
WCF ResponseFormat For WebGet
(4 answers)
Closed 8 years ago.
I have code something like the following:
<OperationContract()>
<Description("")>
<WebGet(Bodystyle:=WebMessageBodyStyle.Bare, UriTemplate:="TestConnection")>
Function TestConnection() As String
Public Function TestConnection() As String Implements ITestSvc.TestConnection
WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain"
Return "Connection Success"
End Function
But it returns is <string xmlns='...'>Connection Success</string>
How can I have only "Connection Success" to be returned without XML wrapper. I know that we can do something with MessageEncoder. But, I want to have it available at operation level (certain operations need XML/JSON wrappers and certain operations don't).
Can anyone help me on this?
here is the simplest solution to return plain text. Set response format to xml and set outgoingresponse to text/html. Should do the trick.
[WebGet(ResponseFormat = WebMessageFormat.Xml)]
public string DoWork()
{
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
return "THIS IS PLAIN TEXT";
}
There is one way how to achieve this if you're dealing with HTTP, it's not exactly nice, but I thought I could mention it.
You can set the return type of your method to void and just output your raw string directly into the response.
[OperationContract]
[WebGet(UriTemplate = "foo")]
void Foo()
{
HttpContext.Current.Response.Write("bar");
}
The answer is here WCF ResponseFormat For WebGet (and it worked for me)