Combine ADO.NET Data Service and custom ServiceContract in the same class? - c#

I have an ADO.NET Data service that I run through WCF:
public class AdminService : DataService<BOPApplicationAccessEntities> {
public static void InitializeService(DataServiceConfiguration config) {
config.UseVerboseErrors = true;
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
config.SetEntitySetAccessRule("*", EntitySetRights.All);
}
}
I'd like to add some custom methods to it, such as the following contract
[ServiceContract]
public interface IAdminService {
[OperationContract]
void RequestAccess(int applicationID, string username);
}
If I add the decoration and implement the method on the data service, an error is thrown when a client tries to connect, saying:
AdminService implements multiple servicecontract types, and no endpoints are defined in the configuration file.
Is it not possible to add service contracts onto an ADO.NET data services service?

The error states that the service exposes multiple contracts (interfaces), which is true, because you just added a new one. The host is not able to work based on implicit default values anymore, because it does not know which service interface to host on which endpoint.
Make sure you have an explicit endpoint defined in your service configuration file for each contract your service implements. Thing will start to work for you again after that, though you might need to update the service reference in your client application after making the modifications.
Update: Combine How to disable authentication schemes for WCF Data Services which tells how to explicitly create an endpoint for your WCF Data Service with http://www.west-wind.com/weblog/posts/2008/Apr/10/WCF-REST-Configuration-for-ASPNET-AJAX-and-plain-REST-Services to troubleshoot problems with your specific error message.

Related

WFC Service Not Seeing Operation Contract

I am having a weird problem where I have a wcf service that has some Operation Contracts but when I add the service reference to another project they are there.
When I go to add -> add service reference. I put in the wfc url and the service shows up.
When I look at the operations list I see those endpoints but when I hit "ok" and then I try to find those endpoints in my project they are not found.
How can I go about debugging this?
Make sure you are using the correct Data Anotations on your interface, for example:
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(ExceptionMessage))]
List<student> GetStudents();
[OperationContract]
[FaultContract(typeof(ExceptionMessage))]
void AddStudents(Student student);
[OperationContract]
[FaultContract(typeof(ExceptionMessage))]
void DeleteStudent(long StudentId);
}
You must have a [Service Contract] interface. And it should contain your methods
When you successfully add the service reference, the proxy class will be automatically generated in the project:
And it will automatically generate web.config, web.config contains endpoint information:

Can I use a web api from a web application as a service reference?

Is it possible to add as a reference and call an APIs controller methods as a service on another project? What are the alternatives if this is not possible?
Web API types of applications do not have a 'service reference' anymore. They do not produce WSDL, so you cannot add them like you used to do with SOAP services. No proxy classes are generated... no intelli-sense.
Web APIs are typically called with lightweight http requests and return JSON and not XML based SOAP responses like traditional ASMX or SVC (WCF) services.
You have some reading to do I believe.
To answer your question, you CAN indeed call API services from a web application (say a controller method in an MVC app), but you won't have proxy classes to help you.
https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client
When you create a service reference you end up with a reference to an interface and a client class that implements the interface.
You can follow pretty much the same pattern without a WCF service reference. In fact, that's one of the benefits of depending on an interface. It doesn't matter to your application whether the implementation is a call to a WCF service, an API, or anything else.
First declare an interface that describes how you will interact with the API.
public interface ISomethingService
{
public SomeData GetSomeData(string id);
}
That interface is what your other classes depend on. They'll never know what the implementation is.
Your implementation could be something like this. I'm using RestSharp to create the API client because I like it better than managing an HttpClient:
public class SomethingServiceApiClient : ISomethingService
{
private readonly string _baseUrl;
public SomethingServiceApiClient(string baseUrl)
{
_baseUrl = baseUrl;
}
public SomeData GetSomeData(string id)
{
var client = new RestClient(_baseUrl);
var request = new RestRequest($"something/{id}", Method.POST);
var response = client.Execute<SomeData>(request);
return response.Data;
}
}
In your startup you would register this class as the implementation of ISomethingService and pass the base url from configuration. That would also allow you to pass a different url for development, production, etc. if needed.
Ultimately it's no different from depending on a WCF service. One difference is that a WCF service defines an interface, but in this case you have to do it. That's actually a good thing, because it's better for your application to define its own interface rather than directly depending on the ones someone else provides. You can wrap their interface or API in a class that implements your own interface, giving you control over the interface you depend on.

WCF service as stateless service in Service fabric

I am creating SOAP service (ASMX service) into WCF service with BasicHttpBinding. Same as implemented here
Wrote Interface as follows
[ServiceContract]
public interface IExample
{
[OperationContract]
[WebMethod]
Task<XmlElement> GetDetails ();
[OperationContract]
[WebInvoke(Method = "Get", UriTemplate = "/GetExample")]
Task<string> GetExample (string guid);
}
Implementations of Interface:
public class ImplementInteface: IExample{
public ImplementInterface(){}
public Task<XmleElement> GetDetails(){
//Implementation of GetDetails function
}
public Task<string> GetExample(string guid){
//Implementation of GetExampl function
}
}
After running service fabric, stateless service running properly.
I have legacy code(asmx file) where same structure was already defined and having ATPs for the same. URL where the legacy apis are exposed, I don't want to mess it.
I want to expose new SOAP apis to the same URL.
But, when I try to call new SOAP APIs from stateless service, it is giving me Bad request as an error.
Is there any way to Create these apis into stateless service in service fabric?
It won't work just like that.
SOAP entails enclosing client requests (actually their body) into an XML.
Typing the address into the browser won't create any XML, but send a plain request
So,
Either you use something else to send a SOAP request (e.g. a WCF client, that you must write in C#, or a third-party product like SoapUI)
Or you give up the SOAP requirement and use WCF to create a REST service, which won't require an XML body and can be called via browser
If you decide to go with #2, you must add this attribute in your svc file
Factory="System.ServiceModel.Activation.WebServiceHostFactory"

Secure and loose coupled communication between clients and WCF services using a RoutingService in between

Is it possible to send objects through RoutingService to peer WCF services without having the router know about the exact type of these objects ?
My intention is to create a router once for all, then be able to add new WCF services, dynamically add them to the routing table, and allow clients to communicate with these services without having to stop, change the code of the router, then start it again.
I was thinking of a generic contract like this:
[DataContract]
public class RequestObject
{
}
[DataContract]
public class ReplyObject
{
}
[ServiceContract]
public interface IGenericServiceInterface
{
[OperationContract]
ReplyObject DoJob(string jobType, RequestObject request);
}
I could put this in a common library that all 3 components link to (client, router, services). But, I am not sure, it will be possible to derive new sub classes to allow new clients/services with new data exchanges to be added without having to change the router.
Any advise ? is it possible for the solution to work when encryption is enforced through clients till services ?
Thanks in advance.
There's a good msdn on using the Message class in WCF to build contract agnostic endpoints. Does not use routing service, but you could build a router using this:
http://msdn.microsoft.com/en-us/library/ms734675.aspx

WCF service queries

I have a WCF service and methods are exposed as below:
public interface IService
{
[OperationContract]
bool Read();
[OperationContract]
bool Write();
}
public class MyService : IService
{
//Constructor
MyService()
{
//Initialization
}
public bool Read()
{
//Definition
}
public bool Write()
{
//Definition
}
}
I have a desktop based application that consumes the Web service through URL.
This web service can be deployed at multiple location so user can connect to any web service by choosing a url from the combo box.
In the client application I create a Service client dynamically as shown below:
ServiceReference1.DXMyServiceClient _client = null;
_client = new DXMyServiceClient ();
_client.Endpoint.Address = new System.ServiceModel.EndpointAddress(url);
Questions
While debugging I notice whenever I call any methods of web service each time the constructor of MyService is invoked ( if I am connected to the same service).
like for example when I do:
_client.Read();//MyService () constructor is called
_client.Write();//MyService () constructor is called
The problem is I have to do all the initialization again.. like if I connecting to the database then I have to again build the connection string and all stuff..
Is this the natural behavior or I am doing something wrong?
Secondly,
I want to validate user for the valid url ( of web service ). If it is connecting to the valid url or not.. I am doing that through Ping command..
What is the best approach for that!!
Questions While debugging I notice whenever I call any methods
of web service each time the constructor of MyService is invoked
(if I am connected to the same service).
The problem is I have to do all the initialization again..
like if I connecting to the database then I have to again
build the connection string and all stuff..
Yes, that's the default behavior, and the recommended behavior. You should NOT rely on any state on your service side! That is generally not a good idea and can lead to a multitude of problems.
In its recommended "per-call" mode, a WCF service has a ServiceHost() class instance running, which will listen for incoming requests / messages. Each time a request comes in, a new, fresh instance of the service class (that implements your service contract) is constructed to handle the request - just like each time you hit a URL in ASP.NET, your page class is instantiated to handle the request.
Yes, of course - this means you should keep your service classes simple and lean and not do a lot of initialization / state management. Anything that needs to be persisted between service calls should be put in a persistence store, like a database, anyway.
You should look at the ServiceBehaviorAttribute class and it's InstanceContextMode property. It controls the lifetime of your service object.
The problem is I have to do all the
initialization again.. like if I
connecting to the database then I have
to again build the connection string
and all stuff..
Is this the natural behavior or I am
doing something wrong?
By default InstanceContextMode is set to PerSession and ConcurrencyMode is set to Single. However, if you don't use session, basically every time you call service new instance is created. This is desired behavior because it is considered more scalable. If it is a problem for you, you should implement session between subsequent calls then for every session you will get one instance of your service.
Here is a guide how to do that: Using Sessions.

Categories

Resources