Is there any way to restrict Operation to only available to REST consumers and not to SOAP consumers?
For example:
[OperationContract]
List<Response> GetResponses(int orderID);
[OperationContract]
[WebGet(UriTemplate = "{orderID}/responses",
ResponseFormat = WebMessageFormat.Json)]
List<Response> GetResponses(string orderID);
While REST consumers can only tackle second method, SOAP consumers see both methods, but in any case they should use first method. So I want to show first method to SOAP consumers only and second to REST consumers only. Can I achieve my goal without creating new service?
What you can do is to separate contracts, one for the SOAP exposed, second for the REST exposed, and then make your service implement both :
SOAP contract
[ServiceContract]
public interface IDummySoap
{
[OperationContract]
List<Response> GetResponses(int orderID);
}
REST contract
[ServiceContract]
public interface IDummyRest
{
[OperationContract]
[WebGet(UriTemplate = "{orderID}/responses",
ResponseFormat = WebMessageFormat.Json)]
List<Response> GetResponses(string orderID);
}
Service implementation
public class DummyService : IDummySoap, IDummyRest
{
public List<Response> GetResponses(int orderID)
{
// Implementation
}
public List<Response> GetResponses(string orderID)
{
// Implementation
}
}
Then those who want to call your service by SOAP will use the SOAP contract and the others the REST contract.
Related
I have a very strange and obscure issue with WCF services that I was hoping to get some insight on:
I am working a WCF service that we are building to replace one that we no longer have source code for. For some reason, in the new WCF service, everything is forced through a single paramater called "request". Using the WCF test client, this is what it looks like
On the "correct" service, this is what it looks like:
Is there any reason why this would be happening? I've defined all of the requests as follows:
[ServiceContract]
public interface IMyService
{
[OperationContract]
string SomeRequest();
}
Which seems correct, but there may be something I've overlooked that is causing this.
In your original WCF service, there is a request function parameter, and it has a definition similar to the following:
[ServiceContract]
public interface IMyService
{
[OperationContract]
Request SomeRequest(Request request);
}
[DataContract]
public class Request
{
string documentId;
[DataMember]
public string DocumentId
{
get { return documentId; }
set { documentId = value; }
}
}
In the new wcf service:
[ServiceContract]
public interface IMyService
{
[OperationContract]
string SomeRequest(string documentId);
}
So this is because the function parameters are different. Originally your parameter was class, but later changed to string, so the display in WCFTestClient is different.
My interface look like this:
[ServiceContract]
public interface IMyService
{
[OperationContract]
myConnectedService.SomeComplexResponseType someMethod(myConnectedService.SomeComplexRequestType request);
}
My implementation look like this:
public class MyService : IMyService
{
myConnectedService_client client = new myConnectedService_client();
public myConnectedService.SomeComplexResponseType someMethod(myConnectedService.SomeComplexRequestType request)
{
myConnectedService.SomeComplexResponseType response = client.connectedServiceMethod(request);
return response ;
}
}
The error i get when i am trying to run my service:
Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.
and
error CS0644: 'System.ComponentModel.PropertyChangedEventHandler' cannot derive from special class 'System.MulticastDelegate'
I have created a WCF service and my interface looks like below:-
[ServiceContract]
public interface IService1
{
[OperationContract(Action = "GetData")]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
here i am using Action name and when i am generating WSDL from this service i am getting operation name like below :
but when i am using wildcard for action like below :
[ServiceContract]
public interface IService1
{
[OperationContract(Action = "*")]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
here i am not getting operation name in my WSDL.
My question is that how can i use wildcard by generating operation name in WSDL. Please help me to solve this issue or give me suggestions for achieving this.
You can only use [OperationContract(Action = "*")] if your service operation takes a Message object and returns a Message object or void.
See the MSDN documentation for OperationContractAttribute.Action Property
I have this GREAT WCF service that returns Data from EF.
public class HistoryDataService : DataService<HistoryEntities>
{
#region Public Methods
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
[WebGet]
public IQueryable<History> GetHistoriesById(int recordId)
{
return CurrentDataSource.Histories.Where(d => d.RecordId == recordId);
}
#endregion
}
I have other services that I added something like:
[WebGet(UriTemplate = "eventdetails/{id}", ResponseFormat = WebMessageFormat.Json)]
to make it more of a traditional RESTful service, however, when I add it I get various errors like:
... both defines a ServiceContract and inherits a ServiceContract from type System.Data.Services.IRequestHandler.`
How do I add this property or is it even possible?
It would save you a lot of time to use WCF Data Services or OData as it is called. You'll get both JSON and XML output for your web service response. Your choice. : )
WCF Data Services
What is the best practice for multiple WCF end point types? i.e.: JSON, JSONP, SOAP & POX? I am using WCF 3.5.
For instance, I have the following JSONP web service:
namespace RivWorks.Web.Service.JSONP
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceContract(Name = "Negotiate", Namespace = "http://rivworks.com/Services/2009/01/15")]
public class Negotiate //: svcContracts.INegotiateService
{
#region Constructors
public NegotiateService() { }
#endregion
#region Methods
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[JSONPBehavior(callback = "method")]
public dto.NegotiateSetup GetSetup(string method, string jsonInput)
{ … }
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[JSONPBehavior(callback = "method")]
public List<dto.NegotiateSetup> GetSetupAll(string method, string jsonInput)
{ … }
#endregion
}
}
Now, I need to expose a SOAP and POX version. My initial thought was to create a WCF Application Project for each service type endpoint. Then publish each one to an App directory under the main website.
RivWorks.Web.Service.SOAP -> http://rivworks.com/services/soap
RivWorks.Web.Service.POX -> http://rivworks.com/services/pox
RivWorks.Web.Service.JSON -> http://rivworks.com/services/json
RivWorks.Web.Service.JSONP -> http://rivworks.com/services/jsonp
I have an internal “Bus” that the working code lives in. I just want to wrap that bus code with service endpoints of various types. What is the best practice way to do this?
PS: Is there a tool for merging the WCF web.config(s) into the main site’s web.config?
TIA
-kb
UPDATE:
How do you go about handling the different decorators that can be applied to a Method signature. i.e. - compare the following Methods (which are identical) and the decorators associated with them:
Decorator for a POX endpoint:
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml)]
public bool ValidateUser(string UserName, string Password)
{
...
}
vs
Decorator for a JSON endpoint:
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public bool ValidateUser(string UserName, string Password)
{
...
}
And here is another example where the method signature itself changes:
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[JSONPBehavior(callback = "method")]
public dto.NegotiateSetup GetSetup(string method, string jsonInput)
{
// Deserialize the input and get all the data we need...
JObject o = Newtonsoft.Json.Linq.JObject.Parse(jsonInput);
string urlRef = String.Format("{0}", o["ref"]).Drop("\"");
string clientDate = String.Format("{0}", o["dt"]).Drop("\"");
string stringProductID = String.Format("({0})", o["productId"]).Drop("\"").Drop("(").Drop(")");
string SKU = String.Format("{0}", o["sku"]).Drop("\"");
string env = String.Format("{0}", o["env"]).Drop("\"");
string stringCompanyID = String.Format("({0})", o["CompanyId"]).Drop("\"").Drop("(").Drop(")");
string boolPortalFlag = String.Format("({0})", o["PortalFlag"]).Drop("\"").Drop("(").Drop(")");
...
}
vs a POX endpoint type:
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml)]
public dto.NegotiateSetup GetSetup(string urlRef, string clientDate, string stringProductID, string SKU, string env, string stringCompanyID, string boolPortalFlag)
{
...
}
Why would you want a separate project? WCF can expose many services on many endpoints, just in a single project.
Simply add the additional endpoints as .svc files. Do whatever you need to do with routing if you're sensitive to the ".svc" at the end (though remember that humans don't see the .svc).