I'm currently having an issue getting data back from a REST API. The REST API displays the correct results in a browser, and the client is successfully connecting to the API to request the data (debugging and stepping through shows it all working), but no matter what I do the Client then says the response is null (or throws various errors).
For testing purposes, I've made a very simple function, Bob, which just returns whatever you send it, but the real functions that grab data do exactly the same.
The REST API Controller
namespace SiteServicesAPI.Controllers
{
public class SiteServicesController : Controller
{
private readonly SiteServices _siteService;
public SiteServicesController()
{
_siteService = new SiteServices();
}
public string Bob(string Bob)
{
return _siteService.Bob(Bob);
}
}
}
REST API SiteServices function call
namespace SiteServicesRole
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class SiteServices : ISiteServicesContract
{
public SiteServices()
{
}
public string Bob(string Bob)
{
return Bob;
}
}
}
REST API web.config system.serviceModel
<system.serviceModel>
<services>
<service name="SiteServicesRole.SiteServices" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="SiteServicesContracts.ISiteServicesContract" behaviorConfiguration="web">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Hitting the REST API with a browser works correctly.
So, going to localhost/SiteServicesAPI/SiteServices/Bob?Bob=Bob correctly return the string "Bob"
The real functions return the correct responses too.
Client side:-
Client interface to REST API
namespace SiteServicesContracts
{
[ServiceContract]
public interface ISiteServicesContract
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "Bob", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
string Bob(string Bob);
}
}
Client proxy setup and call to REST API
namespace SiteServices
{
public class SiteServicesClient : ISiteMessages, ISiteSettings
{
private readonly string _endpoint;
public SiteServicesClient(string endpoint)
{
_endpoint = endpoint;
}
private ISiteServicesContract GetProxy()
{
var channel = new ChannelFactory<ISiteServicesContract>(new WebHttpBinding(), _endpoint);
channel.Endpoint.Behaviors.Add(new WebHttpBehavior());
return channel.CreateChannel();
}
public SiteSettings GetSiteSettings(string siteIdent, string publicKey)
{
var proxy = GetProxy();
SiteSettings siteSettings;
try
{
var Bob = proxy.Bob("Bob");
}
catch (Exception ex)
{
return null;
}
return siteSettings;
}
}
}
Stepping through with the debugger on both sides shows the client connecting to the REST API correctly, and the REST API going through and returning the data correctly, however the Client then either throws an error or sets the value to null.
Yesterday this was giving me a deserialisation error (sorry, I don't have the error message any more).
To try to fix the original serialisation error from yesterday, I changed the REST API to return a Json string (as it was expecting one):-
public JsonResult Bob(string Bob)
{
return Json(new { Bob = _siteService.Bob(Bob) }, JsonRequestBehavior.AllowGet);
}
This didn't throw any errors, but the return value in var Bob in the Client was null.
Today, it's giving me an XML error instead, even though it's set to use Json:-
There is a problem with the XML that was received from the network. See inner exception for more details.
Inner Exception: Unexpected end of file.
So I shrugged and set it to return a simple XML string instead:-
<Bob>Bob</Bob>
This gave me the error:-
OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'BobResponse'.
This got me excited, I was in the right ballpark, so I changed the element from Bob to BobResponse:-
<BobResponse>Bob</BobResponse>
This gave me the error:-
OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'BobResponse' and namespace 'http://tempuri.org/'. Found node type 'Element' with name 'BobResponse' and namespace ''
Fine, I added the namespace:-
<BobResponse xmlns="http://tempuri.org/">Bob</BobResponse>
New error:-
Error in deserializing body of reply message for operation 'Bob'. End element 'BobResponse' from namespace 'http://tempuri.org/' expected. Found text 'Bob'. Line 1, position 45.
So I tried embedding the response inside another element:-
<BobResponse xmlns="http://tempuri.org/"><Bob>Bob</Bob></BobResponse>
This no longer throws an error, but I'm back to the var Bob in the client being set to null.
Could someone please point me in the correct direction to successfully return data to the client (preferably in Json rather than XML)?
Thanks!