I want to write a high level design document for a application which will expose it's webs ervices for various clients. For this purpose I need to provide the WSDL of webservices that we will develop in the future at server side. I've use web services earlier but never drill down in the details of WSDL.
I searched a lot and found that I need to generate WSDL using XML and XSD. Well, I yet to design both and I think this would be my first step.
Now my concern here is that it is very difficult to work with raw XML and I am not master in WSDL terminology.
Can anyone suggest what are the high level steps that one should perform to create a simple WSDL with some fault information in it?
Any insight would be helpful.
Thanks guys.
It is probably easier to just use WCF to create your WSDL for you. You just need to define your OperationContracts and DataContracts. You don't have to implement the operations just define what they are in an interface.
Actually if you are following contract first development you should generate your "Messages" first .
In classic Web services you would actually start with XSDs for your requests, and responses. Then generate the code from the XSDs to guarantee that your data types are compliant with SOAP. Fortunately the DataContractSerializer has become very smart and will take care of your data types for you.
With that in mind, you should generate your Service Contract(s) and Request / Response messages (Data Contracts) first. When you expose a mex endpoint in WCF your WSDL will be generated for you. Creating your own WSDL can be very complex and really the only reason you should attempt it is if you actually want to hide functionality from certain consumers. Even if you wanted to generate your own WSDL for this reason, it would still be easier to let WCF create if for you and then alter it as you saw fit.
Let's stop here and see if you have any further questions.
My motivation for contract-first web services was to allow the service and the client to be written in parallel by different developers. Using WSDL and "Add Service Reference", you have to publish the service before you write the client.
As an alternative, don't go through WSDL. You can write one .NET interface that is shared by both the client and the service. This class will generate a WCF proxy directly from an interface:
public interface IServiceClientFactory<TServiceInterface>
{
void CallService(Action<TServiceInterface> action);
TResult CallService<TResult>(Func<TServiceInterface, TResult> function);
}
public class ServiceClientFactory<TServiceInterface> :
IServiceClientFactory<TServiceInterface>
where TServiceInterface : class
{
class Client : System.ServiceModel.ClientBase<TServiceInterface>
{
public TServiceInterface Service
{
get { return base.Channel; }
}
}
public void CallService(Action<TServiceInterface> action)
{
Client client = new Client();
try
{
action(client.Service);
client.Close();
}
catch (Exception)
{
client.Abort();
throw;
}
}
public TResult CallService<TResult>(Func<TServiceInterface, TResult> function)
{
Client client = new Client();
try
{
TResult result = function(client.Service);
client.Close();
return result;
}
catch (Exception)
{
client.Abort();
throw;
}
}
}
More details at Adventures in Software.
Related
TL;DR:
What is a good and testable way to implement the dependency between the ViewModels and the WCF services in a MVVM client?
Please read the rest of the question for more details about the problems I encountered while trying to do this:
I am working on a silverlight client that connects to a wcf service, and I want to write unit tests for the client.
So I'm looking for a good solution for using the wcf clients in my ViewModels and testing that interaction. I have found two solutions until now:
Solution 1: This is actually how I have implemented it until now:
public class ViewModelExample
{
public ViewModelExample(IServiceClient client)
{
client.DoWorkCompleted += ..
client.DoWorkAsync();
}
}
//This is how the interface looks like
public interface IServiceClient
{
event EventHandler<AsyncCompletedEventArgs> DoWorkCompleted;
void DoWorkAsync();
}
//I was able to put the interface on the generated clients because they are partial classes, like this:
public partial class GeneratedServiceClient : IServiceClient
{
}
The good part: it's relatively easy to mock
The bad part: my service client lives as long as my ViewModel, and when I have concurrent requests I don't know which answer belongs to which request.
Solution 2: Inspired by this answer
WCF Service Client Lifetime.
public class ViewModelExample
{
public ViewModelExample(IServiceFactory factory)
{
var client = factory.CreateClient();
client.DoWorkCompleted += ...
client.DoWorkAsync();
}
}
The good part: each request is on a different client, so no more problems with matching requests with answers.
The bad part: it's more difficult to test. I would have to write mocks for both the factory and the wcf client every time. This is not something I would like to do, since I alreay have 200 tests... :(
So my question is, how do you guys do it? How do your ViewModels talk to the wcf services, where do you inject the dependency, and how do you test that interaction?
I feel that I'm missing something..
Try having a Func<IServiceClient> injected into your VM instead of the a client instance; you'll have a 'language-level factory' injected instead of building a class for this. In the factory method you can instantiate your client however you want (each access could create a new instance for that for example).
The downside is that you'll still have to touch your tests for the most part, but I assume it will be less work:
public ViewModelExample(Func<IServiceClient> factoryMethod)
{
var client = factoryMethod();
client.DoWorkCompleted += ...
client.DoWorkAsync();
}
The WCF service should have it's own tests that confirm the functionality of itself.
You should then be mocking this WCF service and writing unit tests within your consumers.
Unfortunately, it's a pain and something we all have to do. Be pragmatic and get it done, it will save you getting bitten in the future.
Are you using IoC container by a chance? If you had, this problem would be totally mitigated by container (you'll simply register IService dependency to be created as brand new upon each request).
If that's not the case, then
I would have to write mocks for both the factory and the wcf client every time
is how you deal with this kind of "problems". The cost is relatively small, probably 2-3 extra lines of code per test (all you have to do is setup factory mock to return service mock, which you do need either way).
Imagine I have the following, standard WCF, code :
[ServiceContract]
interface ICustomerService {
[OperationContract]
Customer GetCustomer();
}
public ICustomerService {
public Customer GetCustomer()
{
return MyStore.WhatIsNeeded();
}
}
This is working well and allows me to distribute the service and the consuming code.
Is it possible (and is it a good idea) to completely bypass the WCF engine if working in a single box ?
In fact, I want the app to be able to run on farm servers, or on small single box servers.
To reduce WCF messaging cost, I'd like to have something like :
ICustomerService service = null;
if(singlebox)
{
service = new CustomerService(); // Direct instanciation of the service class. No WCF here ...
}
else
{
service = new CustomerServiceClient(); // Wcf client
}
var cust = service.GetCustomer();
If wrapped properly, can this technique reduce server charge ?
That won't work because the client will be attempting to access an endpoint for a service that no longer is exposing one. The WCF plumbing is required for the both the service and the client. For single box scenarios, look at the NetNamedPipeBinding which is the WCF plumbing done through the equivalent of shared memory.
This will surely reduce the overhead of WCF runtime. I'd create a factory class which will check if(singlebox) and new up the right implementation of ICustomerService.
We have already Business logic layer available in our application. It has lots of classes. and this is in separate library(.Dll). Now we want to use this in to our WCF Service. For that We create new project and gave reference to that .Dll. But we are not able to see our class .. I verify that class is public..
Could you please let me know what should I do?
Here I am attaching my code what I need to do
My Business Layer class
namespace BusinessLayer
{
public class MessageContext : Dictionary<string, object>
{ ....}
}
Now I am reference this Project to my WCF project and tried to expose this class into WCF client. So I Create one MessageContextHelper class which inherit from MessageContext the code is following
namespace WCFService
{
public class MessageContextHelper : MessageContext
{ ...... }
}
On client I am not able to get MessageContextHelper class.
Thanks
JK
WCF doesn't send business logic classes to the client. If you're using the SOAP version of WCF (BasicHttpBinding for example) then what WCF will expose is methods that are in your service contract. Your client can call those.
So if you have methods in a business logic class that you want exposed, create methods in your WCF service that will in turn call the business layer methods.
A very rudimentary (and not complete) version would look something like this:
namespace WCFService
{
public class MyService: IMyService
[OperationContract]
public String DoSomeStuff() {
return MessageContext.DoSomething();
}
}
You absolutely cannot (and should not) use your business layer from your client code. As the previous reply message, WCF does not send your business class to the client. Think about how long it will take to send. The business layer (your dll) should be used on the server only. Your WCF should only accept modified/new data from the client, pass the data to the business layer, and then return the results to the client.
I am working on an n-Tier application using WCF between the layers such that:
Tier 1: Silverlight application
Invokes the search request
IClientBroker clientBroker = UIContext.CreateWcfInterface<IClientBroker>("Data/ClientBroker.svc");
clientBroker.BeginSearchForClients(SearchTerm, 20, (result) =>
{
SearchResult[] results = ((IClientBroker)result.AsyncState).EndSearchForClients(result).ToArray();
// do stuff, update UI, etc.
}, clientBroker);
Tier 2: is a WCF web service using basicHttp for Silverlight to call. This is acting as a proxy to the 3rd tier.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
class ClientBroker : IClientBroker
{
[OperationContract] // as defined in IClientBroker
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
ClientBrokerClient clientBroker = CreateClientBrokerClient();
SearchResult[] searchResults=clientBroker.SearchForClients(keywords, maxResults);
return searchResults;
}
}
Tier 3: is the "server", in that this offers a net.tcp endpoint (allowing secure clients to connect without using Silverlight). This is the ultimate target of a request.
public class ClientBroker : IClientBroker // note this is different to tier 2 interface
{
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
// do stuff
if (maxResults.HasValue)
{
return results.Take(maxResults.Value).ToArray();
}
else
{
return results.ToArray();
}
}
}
So my calls go:
Silverlight -> httpBasic -> IIS-hosted Proxy WCF service --> net.tcp --> EXE-hosted WCF service
This works well. I can pass headers through the layers, and maintain sessions, etc. And it is pretty trim.
BUT it takes only a few calls through this to cause a Timeout in the communication.
The time the server-EXE takes to do its work is neglible.
The problem I am seeing is that the server "freezes" in returning results to Tier 2.
I think this is to do with a thread getting locked.
I've looked around and see that the ideal way of doing this is to make my Tier 2 run asyncronously, similar to the code below:
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
ClientBrokerClient clientBroker = CreateClientBrokerClient();
clientBroker.BeginSearchForClients(keywords, maxResults, result =>
{
SearchResult[] searchResults=((ClientBrokerClient)result.AsyncState).EndSearchForClients(result);
// how to return results from here?
}, clientBroker);
}
But how do I achieve this when my Tier 1 client is waiting for the result of this method, which will just drop straight out before the callback execute? Am I missing something on my construction of my OperationContract methods?
UPDATE:
I have since put my server (Tier 3) through its paces from a client avoiding Tier 2 by making many requests from it. Seems the net.tcp WCF channel for Tier 3 is rock solid.
UPDATE 2:
This blog post outlined using the IAsyncResult pattern, which I have eluded to here. Am I barking up the wrong tree here? http://blogs.msdn.com/wenlong/archive/2009/02/09/scale-wcf-application-better-with-asynchronous-programming.aspx
UPDATE 3:
Ok, this paragraph from that blog:
"If you are building N-tier WCF
services, you would have WCF service
operations invoking WCF client proxies
for other backend services. In this
case, you would need to make sure that
the middle-tier (routing layer) has
asynchronous service operation
invoking asynchronous WCF proxy
operations. In this way, your
middle-tier won’t run out of threads
when processing many slow operations."
seems to confirm my suspicions that the problem lies in the middle layer (Tier 2). How can I achieve this Begin/End asynchrony? Do I have to do this manually or can I retain VS tools to generate the proxy classes for me? (REALLY don't want to have to do this manually, the contracts have a degree of flux in them)
Well, I think I've solved it. This topic helped me:
wcf service stops after few requests
Basically, I hadn't been closing my client proxies in my Tier 2, which I realise would cause blocking. The evolution of the code was such that I ended up removing using() {} blocks to facilitate exceptions not getting extinguished with the client proxy. However, I have restructured and retested and my Tier 2 code now looks like:
public SearchResult[] SearchForClients(string keywords, int? maxResults)
{
ClientBrokerClient clientBroker = CreateClientBrokerClient();
SearchResult[] searchResults=clientBroker.SearchForClients(keywords, maxResults);
clientBroker.Close();
return searchResults;
}
... and exceptions are not extinguished.
I'm currently in the process of writing a WCF REST service with SubSonic SimpleRepository and the WCF REST Contrib library. The service is going to be hosted on IIS 7. The database is going to be MS SQL Server. I could not really find a good example which is using this combination of technologies on the internet. The service should expose a database in a RESTful manner but also contains some business rules (e.g. registering users, saving statistics) so I can't use ADO.net Data Services. Because there are going to be a lot of clients accessing the service at the same time it's important that the service can serve several clients at the same time.
For good performance I want to use the following service behaviour:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, ConcurrencyMode=ConcurrencyMode.Multiple)]
There are no instance variables in the Service class and as I understand it, those attribute values cause new a instance of the service class to be created for every call (not per session because it is called over https).
I used the following simple class for creating the SimpleRepository once (singleton):
public class DB
{
private static SimpleRepository _Repository;
public static SimpleRepository Repository
{
get
{
if (_Repository == null)
{
_Repository = new SimpleRepository("5Drive", SimpleRepositoryOptions.RunMigrations);
}
return _Repository;
}
}
}
Here is an example method of my service:
Interface:
[OperationContract]
[WebGet(UriTemplate = "vehicles")]
[WebDispatchFormatter]
Vehicles GetVehicles();
Implementation:
public Vehicles GetVehicles()
{
// get all vehicles for the logged in user
var vehicles = from v in DB.Repository.All<Vehicle>()
where v.UserID == GetUserID()
orderby v.Name
select v;
return new Vehicles(vehicles);
}
So, here is my question: can I do it this way? Is SimpleRepository thread-safe? Do I have to create a SimpleRepository in every method instead of using a singleton? What about performance when I do that? I looked at the SimpleRepository source code and I think that the migration code is not thread safe because the "private readonly List migrated;" is not synchronized but I might be wrong.
Maybe I'm missing something and I can just ignore multi-threading and configure IIS differently?
Thanks for your help!