Consuming a RESTful JSON API using WCF - c#

I'm new to WCF (and pretty rusty with .NET in general) so there's a distinct chance this is an answered question and I just missed it.
I'm building an ASP.NET MVC app that will be using a RESTful JSON-based API for its backend. I've been looking into the different options for how to talk to such an API in .NET and it looks like WCF is the most popular choice by far. Reading into WCF some more I now have a basic consumer class that makes a request, which is a start.
But now I need to do more with it, and I'm not making much headway. I need to send a POST to the API with a JSON body. Here's what I have so far:
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Runtime.Serialization;
namespace APIConsumer {
[ServiceContract]
public interface IAPIClient {
[OperationContract]
[WebInvoke(
Method = "POST",
BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/session/login.json"
)]
string SessionLogin(string login_name);
}
public class APIClient : ClientBase<IAPIClient>, IAPIClient {
public string SessionLogin(string login_name) {
return this.Channel.SessionLogin(login_name);
}
}
}
What I can't figure out is the correct way to pass a) ANY data within the POST body & b) a proper serialized .NET object as JSON in the POST body. Is there a good example of how to work that out there somewhere?

If you are wondering how to format the JSON body of your POST to the operation SessionLogin, in your case, it would be very simple. The JSON data would just be:
{"login_name": "someuser"}
The WCF framework will handle mapping that data to your operation, and will pass the value "someuser" to the parameter login_name for you. Is this what you needed, or was there a more complex scenario you needed help with?

Take a look at How to: Serialize and Deserialize JSON Data article on MSDN. You also need to make sure to set the content-type in your request to 'application/json' on the client side. Check out this SO question.

I was running into the same problem. Sometimes POST-ing JSON works, but not always. It's unreliable and the reasons for it failing can be mysterious. I ended finding that POST was more work than it's worth, and that you could accomplish the same with GET. If you don't absolutely have to design your service with POST, I have a working example of how to accomplish what you're trying to do with POST with GET here:
http://winsockwebsocket.codeplex.com/
(It's part of a seemingly unrelated project, but just go to the Northwind.Web folder to see a complete working example of send/receving JSON from jQuery to WCF.)

Related

Issue with caching wcf service - "AspNetCacheProfileAttribute can only be used with GET operations"

I have a WCF service which does work but really needs the responses to be cached.
I've followed some guidance online but I receive the following error:
AspNetCacheProfileAttribute can only be used with GET operations.
I've checked this in Postman to be completely sure that my client side code is not making the request in the wrong way, same result there.
The interface looks like this:
public interface INavbar
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
List<Navbar.simpleNav> getNavList();
}
The service returns a List as a JSON object, the 2 changes I made to try and add the caching were to add AspNetCacheProfile attribute to the class and add the caching profile details to my web.config.
Attribute for class:
[AspNetCacheProfile("CacheFor180Seconds")]
web.config:
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="CacheFor180Seconds" duration="180" varyByParam="none"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
As far as I can tell it's all pretty standard stuff however it may be that I'm trying to do this the wrong way so any help is appreciated.
Many thanks
You need to use WebGet rather than WebInvoke
The difference is subtle but important:
WebInvoke
Represents an attribute indicating that a service operation is logically an invoke operation and that it can be called by the WCF REST programming model.
WebGet
Represents an attribute indicating that a service operation is logically a retrieval operation and that it can be called by the WCF REST programming model.
And further down, in the remarks section for WebInvoke:
The WebInvokeAttribute attribute is applied to a service operation … and associates the operation with a UriTemplate as well as an underlying transport verb that represents an invocation (for example, HTTP POST, PUT, or DELETE). … The WebInvokeAttribute determines what HTTP method that a service operation responds to. By default, all methods that have the WebInvokeAttribute applied respond to POST requests. The Method property allows you to specify a different HTTP method. If you want a service operation to respond to GET, use the WebGetAttribute instead.

How to deserialize in C# something that was serialized in JQuery?

. .
It's been a while since I've done this, and I'm trying to shake off the rust.
I'm trying to set up an AJAX structure in ASP.NET using VS2010.
I have a JQuery form submit that looks something like this (greatly simplified for example purposes):
function FormSubmit () {
$.post('SomeHandler.asmx/SomeFunction',
$("#form1").serialize(),
function(data) {some data handler}
);
}
My "SomeHandler.asmx/SomeFunction" is a C# function that takes my form data and processes it.
To my knowledge, the SomeHandler.asmx assumes XML deserialization, but the JQuery serializes it as an HTML encoded string, not as XML.
I suppose to use an analogy, one side is speaking in English, but the other side is expecting to hear French.
How do I get around this? (For example purposes, let's say my form has a text field -- we'll call it "txtField", and a drop-down list -- let's call it "lstDropDown".)
Thanks in advance for your help!
In your asmx file make sure you use the following attribute flags on your web methods that accept and respond with json:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string SomeWebMethod()
{
//blah
}
Also, make sure the web service class has the follow attribute flag:
[System.Web.Script.Services.ScriptService]
public class MyWebService : System.Web.Services.WebService
{
...
}
One last thing: if you're serializing the data on the client side, you need to use the following ajax setup:
$.ajaxSetup({ contentType: "application/json; charset=utf-8" });

ASP.NET: Web Service or WCF for simple ajax call?

I just want to simply call a method on my web service via ajax and have it return a value.
Should I use "WCF Service" , "AJAX-Enabled WCF Service" , or "Web Service"
Which is the easiest?
Use a generic HTTP handler instead. They are simpler to code.
You should use Ajax-Enabled WCF service. I don't remember the name exactly but it should be marked with an attribute to be accessible from JS.
You should never use the "Web Service" template unless you're maintaining existing code and can't change.
If you are just calling a single method use ScriptMethod
You can code it inline with the page that it is used on.
http://www.asp.net/ajax/tutorials/understanding-asp-net-ajax-web-services
Using the ScriptMethod Attribute
The ScriptService attribute is the
only ASP.NET AJAX attribute that has
to be defined in a .NET Web Service in
order for it to be used by ASP.NET
AJAX pages. However, another attribute
named ScriptMethod can also be applied
directly to Web Methods in a service.
ScriptMethod defines three properties
including UseHttpGet, ResponseFormat
and XmlSerializeString. Changing the
values of these properties can be
useful in cases where the type of
request accepted by a Web Method needs
to be changed to GET, when a Web
Method needs to return raw XML data in
the form of an XmlDocument or
XmlElement object or when data
returned from a service should always
be serialized as XML instead of JSON.
The UseHttpGet property can be used
when a Web Method should accept GET
requests as opposed to POST requests.
Requests are sent using a URL with Web
Method input parameters converted to
QueryString parameters. The UseHttpGet
property defaults to false and should
only be set to true when operations
are known to be safe and when
sensitive data is not passed to a Web
Service. Listing 6 shows an example of
using the ScriptMethod attribute with
the UseHttpGet property.
If those are your only options, I've found the AJAX-Enabled WCF Service to be the simplest to work with. It's still WCF, but it templates out for you the proper web.config setup and ditches the interface that the plain "WCF Service" template gives you. It seems to be the closest thing in the whole WCF mess to the old ASMX-style as far as being dirt simple to get going.
Just as another alternative, if you happen to be able to use ASP.NET MVC in your webforms project and just need this for an ajax call, you could skip the web service hoopla altogether and create a simple JSON result for your AJAX call like so:
// put this method in a controller
public JsonResult AjaxJsonTest(string who) {
var result = new {
Success = true,
Message="Hello, " + (who ?? "world!")
};
return Json(result, JsonRequestBehavior.AllowGet);
}
And then you can call it from jQuery like this:
<script language="javascript" type="text/javascript">
function AjaxTestClick() {
$.ajax({
type: "POST",
url: '<%: Url.Action("AjaxJsonTest", "Test") %>',
data: { who: 'whomever' },
success: function (resultData) {
if (resultData.Success) {
alert(resultData.Message);
}
else {
alert('Ajax call failed.');
}
}
});
}
</script>
Tons of options - pick what suits your situation best.

WCF Ajax service - How can I pass an Array or JSON to the service? What should the method parameter type be?

I have a very simple WCF service I would like to pass it an array or json?
[OperationContract, WebGet(ResponseFormat = WebMessageFormat.Json)]
public string GetPreDisplay(string inputData)
{
//DoSomething with inputData
return "Sweet!";
}
My javascript...
var data = [paymentControls['claimNum'], paymentControls['claimSeq']];
$lps.GetPreDisplay(data, onComplete);
Obviously string is the wrong type. Can anyone point me in the right direction?
Thanks,
~ck
With ASP.Net MVC you can return data as an ActionResult, there is a method "Json" which converts the data to the correct format. Have a look at this other question:
wcf json web service

Session state with jQuery/Ajax and ASP.NET web service

I'm trying to consume an ASP.NET web service, using jQuery's Ajax methods. I want the return type of the web service method to be JSON-formatted data, and I'm marking the method with these attributes:
[WebMethod(EnableSession = true)]
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
public MyObject[] GetMyObjects(int pageIndex) {/*...*/}
I want to also return from the method some sort of value that would indicate whether the session has expired, either in the SOAP headers an output parameter. How would I do this with jQuery syntax? Should I wrap my MyObject[] array in a serializable ResponseType object that contains a SessionValid property and the payload? Or is it possible to use SOAP headers and output parameters with jQuery?
Thanks.
Should I wrap my MyObject[] array in a serializable ResponseType object that contains a SessionValid property and the payload?
This is the way I usually go with.
Not time consuming to implement and very easy to maintain.
[Serializable]
public class MyReturn
{
public MyObject[] MyObjectList { get; set; }
public bool SessionExpired { get; set; }
}
Then handle it where you do the AJAX call.
EDIT: I usually only use
//...
contentType: "application/json; charset=utf-8",
dataType: "json",
//...
in my AJAX calls to be sure the returned type is in JSON format.
I'm not completely familiar with using session in SOAP web services. However, I did stumble on this post which states that the JavaScript will need to account for cookies since this is how the session is maintained.
Although, SOAP may use a different method for tracking session via it's headers, so I don't know if this is accurate.

Categories