I just referenced my application domain layer dll to the new WCF service that I am creating.
On my initial tests I am able to use and return the objects from my domain layer on the WCF service.
Question that come in my mind is none of my domain claseses have [DataContract] attribute so does this create a limitation or problem for me that I should be aware of? Or any other concerns that I should know when using other class library in a WCF project?
You can either use DataContract or Serializable. If you use serializable you need to reference the dll with the types from both the server and the client. This is Ok when you have control of both, but can be a problem if other people want to access your service.
Take a look at this video for a better way of doing it than standard Visual Studio:
http://www.dnrtv.com/default.aspx?showNum=122
First law of distributed object design : don't distribute your objects.
But if you really want because you create a data oriented application, .NET Ria Services is what you want.
Related
I'm migrating a system to its version 2.0.
It's escalating so I want to build a WCF. This is the first time for me working with a WCF so this may be kind of basic, still, any heads up will be very much appreciated.
The existing system consists of a 3 layered proccess.
UI based on WebForms.
Business Layer.
DAL.
For this 2.0 version what I'd like to achieve is to leave webforms behind, moving to a more mvc oriented interface. And, as I've already said, to use some sort of web service to get through in order to connect to my db source.
The question is as follows. I've been investigating and reading about wcf/restful and in the Iservice.cs I can see the interface and the DataContract with its DataMembers. The scratching-head part is that I already have my classes defined on the other layers. So, what is it meant to be done? Should I define my classes inside the WCF one by one aswell? Can't I just reference my DAL/Object Layer and use the resources available there?
Should I add another proyect to the existing VS2010 solution or should I leave the wcf alone?
I'd love to get some input on best practices also, if you may.
If REST is really what you are after, then there are other options for this than just WCF. WCF is generally overkill for most scenarios, so consider looking into:
ASP.NET Web API
ServiceStack
Both options work with ASP.NET MVC and ASP.NET WebForms, although most ASP.NET Web API examples will be used with ASP.NET MVC, which is the scenario you want to use it in it sounds like.
You can treat the ASP.NET Web API or ServiceStack as another layer in your architecture and just reference it like you would the business or data-access layers, as separate projects in your solution.
better way will be, add another separate layer for WCF service give DAL reference to it, at the same time also give DAL reference to BAL. And DON'T give WCF project reference to any one because you want it to be RESTFULL (i.e. to be access only through HTTP, ftp like protocols)
Here Iservice.cs is just interface which exposes methods to the outer world, it depicts what data, in what form and where it will be find. just implement that interface to any repository class in WCF project, which further will get data from DAL for you. Buisness Layer is the Only layer who will talk to Service layer.
Adding DAL reference to BAL is only for the metadata of the entities.
If i was wrong kindly revert me.
Following the instructions to use the Reflection Provider (http://msdn.microsoft.com/en-us/library/dd728281.aspx) everything works well, until I move the classes Order and Item to a Class Library and reference the class library from the web project with the SVC file.
Move the POCO classes into the WCF project all goes well.
Move the POCO classes out of the WCF project into separate assembly, I get a 500 with no explanation.
I want to be able to keep my poco classes in a separate project and expose them with an OData endpoint. What am I doing wrong?
--UPDATE--
The scenario described above is meant to illustrate a problem I have found using the WCF OData Reflection Provider. It is not my real problem, but is easier to explain for illustrative purposes.
Try upgrading to the latest version of WCF Data Services (currently 5.3), if you aren't already on it. I reproduced your issue using the version of WCF Data Services that ships with .Net 4.5, but once I upgraded the references in both assemblies to the latest release of Microsoft.Data.Services using NuGet, the problem went away.
If you're already using the most up-to-date version of WCF Data Services, make sure that both assemblies are referencing the exact same version of WCF Data Services.
If neither of these fix your problem, add the following attribute to your DataService class to get a more detailed error message and stack trace:
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class YourService : DataService<...>
And then please update your question with the results of that (if the solution doesn't immediately jump out from the stack trace).
(disclaimer: I usually don't like answers of the kind that don't help you with your problem but rather explain why your problem isn't the correct problem, but I think it's justified in this case :))
If you think about it, you don't really want to do that:
The Order and Item classes aren't really POCOs at all; they're not 'plain' C# objects; they have data attributes on them, which make them data transfer objects (DTOs).
They belong to the interface between your service and its clients;
The domain entities (or POCOs) Item and Order will, most likely, be a bit more complex, and contain other things besides data, such as operations and business logic.
I believe the correct way to go is to have a rich domain model, in which Order and Item contain a full set of attributes and operations, and on top of that, a DTO layer, which contains only those attributes that your service client needs.
Sending your POCOs over the wire was termed 'the stripper pattern', and I believe it's best avoided.
I have two projects in the same solution, a service and a consumer app. In the service I have many classes that can be instantiated by the consumer app but some classes are not accessible. There's no difference apart from name. All classes are all Public so they should all be seen. Is there any buffering problems or anything else that could cause the problem to behave like this?
Consumer does not get access to Server classes when you use WCF or any other Web Services/Removing technology. Proxy classes are created instead. Think about them as set of Interfaces that are able to call method over app boundaries. You can instantiate proxy classes but when you call method proxy class will go to Service and call corresponding method of class hosted by service.
You need to use Class Library and move move your shared classes there (and deploy dll with Service and Consumer) if both parties use them.
Update (thanks razlebe):
Business logic should not be shared in DLLs. It should be hosted by server. But it will make sense to share supporting classes (for example class that do data formatting) to avoid code duplication.
When you update service class and change interface by:
Adding a method (Your case)
Removing a method
Changing signature
Your consumer needs to learn about the change. You have to update service reference (http://msdn.microsoft.com/en-us/library/bb628652.aspx) to rebuild proxy.
How to update it?
Check here to see how: http://msdn.microsoft.com/en-us/library/bb628652.aspx)
But one image is better than thousand words:
My guess is that the classes that "are not accessible" were created after the last generation of the proxy (classes of the service, client-side). Check if REgenerating the proxy helps.
I am new to DDD and at the moment I try to refactor a project towards a domain driven architecture. The project has a client and a server side (ASMX webservice). Now I created a class libary called "Domain" which is referenced by the client application as well as by the server.
Now I want my SOAP communication to be based on my domain model. But as you know the ASMX webservice creates some kind of proxy class library within the client as soon as a web reference is established.
This results in having each domain entity and value object twice under different namespaces.
Is it possible to use the domain model for communication directly and avoid the generation of the ASMX proxy classes?
How are DTOs used within DDD? As you know, some domain parts might not be serializable (e.g. NHibernate / IList usage) so in the past I often created simpler DTO-versions of my entity classes. Is it a common practice to define DTO entities within the domain?
If you were to use WCF, you could have the service interface and DTO classes in a shared assembly that both the client and the server referenced. Converting your project to use WCF may not be too hard, but there is a lot of learning to do before you get started.
A shared interface assembly is only a good ideal if you wish the client and server to be tightly joined, hence it does not work well unless both side are owned by the same team.
Often trying to use the same classes on the server and client lean to deign problem, however sharing classes when it does fit the design saves a lot of work.
(Sorry I don’t think you can used a shared assembly with asmx, it is more a concept from the remoting side of .net history)
It is not possible to use original domain model (obtained by a reference -not a WEB reference- to the domain model) for communication with the ASMX: you must use the model exposed by asmx that is similar but not the same (i.e. List are transformed in Array).
It's possible -and easy- create many classes from many web-services having the same namespace.
Create a .bat file like this
"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\wsdl.exe" /sharetypes /o:C:\code\MyProxy.cs /namespace:MyProxies http://website/FirstService.asmx http://website/SecondService.asmx
Pause
Where
-"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\wsdl.exe" is wsdl.exe with relative path (it must be on your PC)
-/sharetypes means that you want only 1 namespace in the output
- /o:C:\code\MyProxy.cs is the .cs file name that will contain all the classes created
- /namespace:MyProxies is the namespace for all the classes created
- http://website/FirstService.asmx http://website/SecondService.asmx is the list of webservices that you need to call
- Pause means that you want window's shel to remain open to read the feedback of the operations.
NOTE
1) All instructions must be in one line (don't press enter); Pause in the second line.
2) If /o:C:\code\MyProxy.cs will be part of your solution (i think so) and you use source control, the file must be checked out to be overwritten by wsdl.exe
Should I bind directly to objects returned from a webservice or should I have client-side objects that I bind to my gridcontrols? For instance if I have a service that returns object Car should I have a client side Car object that I populate with values from the webservice Car object?
What is considered best-practice?
In C# do I need to mark my classes as serializable or do something special to them?
This is a good question, which follows the sames lines as two questions I have asked myself:
Large, Complex Objects as a Web Service Result.
ASP.NET Web Service Results, Proxy Classes and Type Conversion.
Both of these may be a worthwhile read for you.
Heres my two bits:
Try to keep the return types of your Web Services to primitives where possible. This not only helps reduce the size of the messages, but also reduces complexity at the receiving end.
If you do need to return complex objects, return them as a raw xml string (I'll explain below).
What I then do is create a seperate class which represents the object and handles it's xml. I ensure the class can be instantiated from and serialized to xml easily. Then both projects (the web service and the client) can reference the DLL with the concrete object in, but there is none of the annoying coupling with the proxy class. This coupling causes issues if you have shared code.
For example (using your Car class):
Web Service (CarFactory) method BuyCar(string make, string model) is a factory method that returns a car.
You also write a Mechanic class that works on Car objects to repair them, this is developed without knowledge of the Web Service.
You then right a Garage class for your application. You add a web reference to the CarFactory service to get your cars, and then add some Mechanic's to your garage and then crack your knuckles and get ready to get some cars from the factory to get them working on.
Then it all falls over, when you get the result of CarFactory.BuyCar("Audi", "R8") and then tell your Mechanic.Inspect(myAudi) the compiler moans, because the Car is actually of type CarFactory.Car not the original Car type, yes?
So, using the method I suggested:
Create your Car class in its own DLL. Add methods to instantiate it and serialize it from/to XML respectively.
Create your CarFactory web service, add a reference to the DLL, build your cars as before, but instead of returning the object, return the XML.
Create your Garage adding a reference to the Mechanic, Car DLL and the CarFactory web service. Call your BuyCar method and now it returns a string, you then pass this string to the Car class, which re-builds its object model. The Mechanic's can happily work on these Car's too because everything is singing from the same hymn sheet (or DLL?) :)
One major benefit is that if the object changes in its design, all you need to do is update the DLL and the web service and client apps are completely decoupled from the process.
Note: Often it can be useful to then create a Facade layer two work with the web services and auto-generate objects from the XML results.
I hope that makes sense, if not, then please shout and I will clarify .
This really depends on what you are getting from the web service. If they are simple data transfer objects and you are only displaying data, then yes, you can bind. If you plan to edit the objects, it may not be usefull as you will need to track changes.
Do your objects and/or collections on the client track changes? If so you can use them.
If you have no change tracking, then you will need to track changes yourself, so you may need to translate the objects or wrap them in something to track changes.
Again, it really depends on what you are getting, what they support, what you are doing with them, as well as what response the server wants back for changes.
One thing you can do is to create client classes corresponding to the web service data contracts with any additional functionality that you want and set the web service reference to reuse existing types. Then there is no reason to create an additional wrapper class to bind to.
If you bind directly to the Web service types, you're introducing a coupling. Should the Web service change in future, this may have undesired side-effects that mean lots of code changes.
For example, what if you're using .asmx Web services today, then shift to WCF tomorrow? That might mean quite a few changes through your code if you've used types that WCF won't serialize.
It's often better in the long run to create specific client-side objects and then translate to and from Web service data contract types. It may seem a lot of work, but this is often repaid greatly when it's time to refactor, as your changes are localised in one place.
If you are the owner of both the web service and the client.
And you need the parameters of the web service calls to be complex classes which contain not only data but also behavior (actual coded logic) then you are in a bit of a pickle when developing these web services using web service frame works.
As suggested in the answer by Rob Cooper you can use pure xml as web service parameters and xml serialization, but there is a cleaner solution.
If you are using Visual Studio 2005 (probably applies the same for 2008), You can customize the way VS creates you proxy as described in this article:
Customizing generated Web Service proxies in Visual Studio 2005
This way you can tell VS to use your own classes instead of generating a proxy class.
Well when I think of it, it's pretty much same solution as proposed by Rob Cooper, with the little twist, that you wont be writing a Facade layer your self but will be using VS itself as this layer.