SharePoint WCF Service and AJAX POST
How to post data using AJAX to a custom RESTful service in SharePoint 2010/13
In our shift to Client (Browser, Html, JS) talking to custom REST Services it's not always obvious how to handle a POST.
Using the UrI Template we can use the Query string in the Request. This seems reasonable for a GET, but with a POST I think it makes more sense to use JSON data in the body of the request. Especially if you have a lot of parameters.
Service Contract
[OperationContract] [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "v1/Create")] MyResponseEntity Create(string name, string description);
The above code creates an OperationContract for the WCF service. Notice that the BodyStyle is set to Wrapped. This makes .Net look for the parameters in the body of the request.
I am using V1 in the URI template to help version the service for future enhancements if needed. This is optional.
AJAX POST using jQuery
myModel.create = function (serviceUrl, myEntity) { var data = JSON.stringify(myEntity); //alert('posting: ' + data); //myEntity looks like { name: "ABC", description: "DEF" } $.ajax({ type: "POST", contentType: "application/json", dataType: "json", url: serviceUrl, data: data, success: function (result) { alert('success'); }, error: function (e) { alert("error:" + JSON.stringify(e)); } }); };
This javascript code creates an AJAX request using jQuery and posts the myEntity to the server. The JSON representation of myEntity is in the body of the request.
Uploading files to a REST service
To push files up there is a slight change. I reviewed methods to use a Stream but didn't have much luck. Here is an approach that worked.
Overview:
- Kendo FileUpload
- Asynchronously uploads to a REST service using the URI template to send the ID as a querystring parameter
- The Service method gets the posted file from the HttpContext
Service Contract
[OperationContract] [WebInvoke( ResponseFormat = WebMessageFormat.Json, Method = "POST", BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "v1/AddFile?id={id}")] MyResponseEntity AddFile(string id);
The ID is simply so I know where to save the files. Here I am just using the UriTemplate and the Bare body style.
MyResponseEntity is optional, and useful if you want to handle issues on the client. However it could be void.
Implementation
//Implementation public MyResponseEntity AddFile(string id) { MyResponseEntity response = new ResponseEntity(); try { HttpContext context = HttpContext.Current; HttpFileCollection postedfiles = context.Request.Files; foreach (string postedFileName in postedfiles) { HttpPostedFile file = postedfiles[postedFileName]; response.message = "I found a file for id " + id; //Do somethings like SAVE.... } response.success = true; } catch (Exception ex) { //logging and exception handling } return response; }
The MyResponseEntity is not really required for this example.
Html
Here I'm using the Kendo FileUpload control.
<input id="fileUpload" name="files" type="file" /> <script> $("#fileUpload").kendoUpload( { localization: { select: "Attach..." }, async: { saveUrl: "myservice/addfile?id=5", //ID should be updated to use your model autoUpload: true } } ); </script>
This provided a reasonably straight forward way to dynamically upload files asynchronously to a REST service.
CodeMonkey Software is a division of JCHMedia www.jchmedia.com