UriTemplate prefix for RESTful WCF web service - c#

I have various interfaces (endpoints) in a WCF service host, each for a completely different concern. In a classic soapy web service, I'm able to define a base host address (e.g. http://myhost.com/) and map each interface to a relative URI (IServiceContract -> service/, IMaintenanceContract -> maintenance/) so I can call them by e.g. http://myhost.com/service/mymethod.
Now I'm taking my first steps towards a RESTful WCF service using JSON as message format for CRUD web requests and the only thing I see to address an operation is by using the UriTemplate field from WebInvoke (or WebGet) attribute. Unfortunately, it doesn't seem that I can put this on the interface, just on operation contract methods.
How can I map each interface to a different relative URI?

Yes, you'll put the base url on the [OperationContract] methods. This is OK though, because you can specify any base url you want. Here is a sample interface that gives you this control.
namespace MyHostApi
{
[ServiceContract]
public interface IMyHostApi
{
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "WhateverYouWant/HelloWorld/{name}")]
string HelloWorld(string format, string name);
}
}

Related

.asmx Service not working when publish for some services

I have a project that needs to integrate with legacy asmx services that contains business logic that I must use. I had problems making use of the channels so were allowed to add attributes to make the services rest.
Now here is the problem, I have tested all the services with post man locally and all calls work perfectly with rest as well as the old application still working. Hosting the web app on my local IIS also works. My problem is that when I publish to the server I have some services saying that [ScriptService] attribute is not there but they are there. Then other services works. What am I missing with IIS or publishing? Here is some Name changed code sections. Had to change due to NDA
//Working Service locally returns xml
[System.Web.Services.WebService(Namespace = "http://TheService.ServiceContracts/2006/09", Name = "MyWorkingService")]
[System.Web.Script.Services.ScriptService]
public class MyWorkingService : IMyWorkingService
{
[System.ServiceModel.Web.WebInvoke(Method = "POST",
RequestFormat = System.ServiceModel.Web.WebMessageFormat.Json,
ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json,
UriTemplate = "/PostMethod",
BodyStyle = System.ServiceModel.Web.WebMessageBodyStyle.Wrapped)]
[System.Web.Services.WebMethod]
public string PostMethod(MyPostObjectClass item)
{
//Business logic
}
}
//Failing Service; locally returns json
[System.Web.Services.WebService(Namespace = "http://TheService.ServiceContracts/2006/09", Name = "MyFailingService")]
[System.Web.Script.Services.ScriptService]
public class MyFailingService : IMyFailingService
{
[System.ServiceModel.Web.WebInvoke(Method = "POST",
RequestFormat = System.ServiceModel.Web.WebMessageFormat.Json,
ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json,
UriTemplate = "/GetDataFromObjectFilters",
BodyStyle = System.ServiceModel.Web.WebMessageBodyStyle.Wrapped)]
[System.Web.Services.WebMethod]
public MyResponseObject GetDataFromObjectFilters(ObjectFilterRequestClass item)
{
//Business logic
}
}
So I looked at my local IIS and the server IIS to try and figure out what is wrong. Matched up the handler mappings, ISAPI filters and the IIS features that is installed on my local to the server. Yet the server kept asking for the script service attribute even if it was on the class.
After a full weekend of no relax time, I ended up creating a new service project to add the services into and then started adding api controllers into the project to run alongside these services. Making use of the same name as the services to make changes less troublesome in the ui application.

Does WCF support Dynamic Parameters?

Does WCF support Dynamic Parameters or Anon Objects?
Can it still work without DataContracts?
like this
// The Service
[ServiceContract]
public interface IMath
{
[OperationContract]
string Add(Object param);
}
Yes you can Call a WCF service from a client without having the contract interface..
For More Details check the following link it il helpful for u
http://www.codeproject.com/Articles/328552/Calling-a-WCF-service-from-a-client-without-having

WCF DataContractSerializer and XMLSerializer both in same service. Possible?

WCF. Framework 4.5.1
Existing web service uses DataContractSerializer.
It now needs to provide a contract that takes XMLSerialized data from a third party as an input parameter and return a serialized object.
Apparently I should be able to decorate that contract with [XMLSerializerFormat].
But this breaks the published site.
i.e. You can't even access the site with a web browser to obtain the wsdl.
Is there some extra work needed in the Web.Config?
[OperationContract]
[XmlSerializerFormat]
[WebInvoke(UriTemplate = "", Method = "POST")]
ResponseMessage Update(RequestMessage instance);
The contract is sitting inside an interface with all of the existing contracts
The interface is decorated
[ServiceContract]
public interface IMyService
{
Thanks
Bob
Problem was that the contract was not specifically decorated with xml.
Apparently the default assumption is JSON. Working declaration:
[OperationContract]
[XmlSerializerFormat]
[WebInvoke(UriTemplate = "Update", Method = "POST",
ResponseFormat = WebMessageFormat.Xml,
RequestFormat = WebMessageFormat.Xml)]
ResponseMessage Update(RequestMessage instance);
The 'Answer' I put up has exposed some very strange behavior.
With the [XMLSerializer] decoration in place, other contracts can no longer deserialize integers. The integer property leaves the client as say 6 and is deserialized as 0. Comment out the decoration and normal behavior resumes.
I will post a separate question about this.

WebService calling another Webservice has different behavior if the first service is responding to a call to it

I've written a C# Windows Service that provides a REST api through WCF. This Service needs to call another web service which also uses a REST api. My service can communicate perfectly with the other service unless someone has made a call my service and it is currently responding. I wrote up a simple test:
public void TestConnection()
{
WebChannelFactory<IOtherService> wf = new WebChannelFactory<IOtherService>(otherURI);
IOtherService service = wf.CreateChannel();
service.Test();
}
[ServiceContract]
public interface IOtherService
{
[WebGet(UriTemplate = "services/account?username=testuser&password=d625a4de623dce36af2b75102eaf0ce7&locale=en-US", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
[OperationContract]
AccountServiceInfo Test();
}
Normally when I call TestConnection it works perfectly, but when someone makes a call to my service that requires me to call TestConnection the other service sees a POST rather than a GET and returns 400. Does anyone have any idea why this might be the case or how I can fix it? Thanks.
When using a WebChannelFactory inside a WCF service that already has an OperationContext, you may need to create a new context before being able to successfully callout using a channel created by the WebChannelFactory.
public void TestConnection()
{
var wf = new WebChannelFactory<IOtherService>(otherURI);
var service = wf.CreateChannel();
using ((IDisposable)service)
using (new OperationContextScope((IContextChannel)service))
{
service.Test();
}
}
http://blogs.msdn.com/b/pedram/archive/2008/07/19/webchannelfactory-inside-a-wcf-service.aspx

WCF RESTful Services Using Interface with Generics

I have an interface similar to this:
[ServiceContract]
public interface IBaseService<T>
{
[OperationContract]
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
List<T> LoadById(string value);
[OperationContract]
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
List<T> Load(string field, string value);
}
These methods are going to be implemented in several services. An example of implementation would be like this:
[ServiceContract]
[ServiceKnownType(typeof(ObjectDTO))]
public interface IObjectService : IBaseService<ObjectDTO>
{
}
My question is, is it possible to setup RESTful services using this architecture using UriTemplates on the OperationContracts in the base service interface? I tried searching around, but didn't see anyone else attempting to setup their RESTful services this way.
This is purely my HO, but I strongly recommend you to try out OpenRasta instead of added-as-an-afterthought-to-a-RPC-based-framework REST support in WCF. This is surely possible in OpenRasta.
Inheritance with web services is something that I've always found very problematic to achieve, as such I strongly advise against it. Instead consider building your web services as stubs and then call into shared logic with similar structure to what you have done.
If you want a way to easily create web services that are configuration-free you should check out servicestack.net. It's an open source web service framework that lets your create REST-full JSON and XML webservices without any endpoint configuration, Service or Operation contracts - using only POCO DataContracts. Here is a live example showing the client and server code needed for creating simple REST web services called by Ajax and Silverlight clients:
Given the way that REST services are consumed I'm not sure that there's any point using generics. You lose all the benefits of strong typing as you switch to what is a dynamic transport.
JSON serialisation is dynamic and not type aware, so why do you need to strongly type your output?
[ServiceContract]
public interface IBaseService
{
[OperationContract]
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
List<object> LoadById(string value);
[OperationContract]
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
List<object> Load(string field, string value);
}
Will produce the same JSON output.
Given that I think your best bet is just to not use generics in REST.
WCF does not allow open generics in its service contracts. It does provide a KnownType and ServiceKnownType attributes that let you "inform" it of your polymorphisms. You can provide a static helper method to the ServiceKnownType attribute that return the collection of known types as well. I've used this to return the types that match my generic configuration.

Categories