One entity shared across two web services? - c#

I'm working on a project where I have 2 web services that need the same entity. The 2 web services are on the same server so on the back-end, they share the same classes.
On the front-end side, my code consumes both web services and sees the entities from both services as separate (in different namespaces) so I can't use the entity across both services.
Does anyone know of a way to allow this to work in .NET 2.0?
I've done this with my entity:
[XmlType(TypeName = "Class1", Namespace = "myNamespace")]
public class Class1
{
public int field;
}
Hoping that my IDE would somehow "know" that the class is the same on both web services so that it wouldn't create separate entities for both classes, but no luck.
Is this possible to do with .NET 2.0 web services?

I think that you can not do that from inside VS but you can manually use the wsdl.exe utility like this:
wsdl.exe /sharetypes http://localhost/MyService1.asmx?wsdl http://localhost/MyService2.asmx?wsdl
Notice the /sharetypes option which turns on the type sharing feature. This feature creates one code file with a single type definition for identical types shared between different services (the namespace, name, and wire signature must be identical).
More info:
Web Services Description Language tool
Framework 2.0 - WebServices Shared Types

I'm not sure about the implementation details with .NET 2.0, but I believe what you want to do is put the common classes in a seperate XSD file and refer to it from within your two WSDL's. This way, the common types have the same namespace between the two services.
Now, how you do this in .NET 2.0 I couldn't give you the specifics on...

Can you check the namespace of the entity? Make sure it is the same in both the web services.

Related

Entity Framework & Portable Class Library

I have a solution containing a WPF Project and a Windows Phone Project, both having a reference to my PCL that contains my Models and ViewModels. I also have a WCF Project that allows me to call a common API. It worked just fine so far.
Now I want to use Entity Framework to communicate with an SQL database so I can make request from my ViewModels. I thought about moving my Models from the PCL to the WCF project, and use them as entities. This implies to reference my WCF project in the PCL.
Just like specified here: Entity Framework for Portable Class Library , I get the following error:
"Failed to add reference to 'System.ComponentModel.DataAnnotations'. Please make sure that it is in the Global Assembly Cache."
which is in reality a Nuget issue. (http://nuget.codeplex.com/workitem/2978). The real reason is that Entity Framework is not compatible with PCLs anymore. From what I read, the Entity Framework 7 will allow me to do so, but it's impossible for now.
Does anyone know a good way to communicate with my database with this configuration ?
Here is my solution:
My Models and ViewModels are still defined in my PCL. Entities are defined in the WCF. I added a class in my WCF that converts an Entity to a Model. An interface that defines each available request to the API in the PCL, and I'm implementing this interface in each platform. Each platform implementation just calls the methods defined in WCF (which means I have to implement every request identically in each platform). I'm using my conversion class in WCF to return a model instead of an entity.
It's not the best solution, but it works while I'm waiting for Entity Framework 7.
I usually store my model within a wcf application behind the services layer.
As a result, my model has no dependencies on UI dlls.

DataContract in a project other than WCF

I have been developing a WCF service for my project. I have multiple projects in my solution, explained below:
WCF Service - WCF Service Project
Business Logic - project contains domain logic
Data Access Layer - for accessing data
Core - project contains the business objects only (Many of them are sent as a response of service call - This contains the classes which are to be shared with client)
Log - project to log errors and activities
Service project puts call to Business project for the respective operation and the Business Logic project intializes the objects of the classes defined in Core object. And these objects are sent as the response of service call.
This is done successfully, i am able to share all public properties of the class defined in Core project. But i am unable to use DataContract/DataMember attributes in the core project as this is a non-WCF project. I need to achieve few tasks for which i have to use DataMember attributes like i dont want to share a property in case of null value, i don't want to share few properties of some objects with the client.
Please tell me if i am mistaken with the approach. And please help me achieving the above, i couldn't find any similar question on the forum.
Edit: (Let me try explaining it better)
All the projects are referenced in the WCF Service Project which consumes those project. This was to keep logical separation.
For Example, The Core project contains a class named User and this class is the return type of a service api. When this API is called, the logic initializes an object of User. And the object is returned as a result to that call.
In this case, i haven't used any [DataContract] attribute for the User class. And it works fine. Now i want to stop sharing few properties of this class, for this i needed to use [DataContract]/[DataMember] attributes, which are not being resolved in the Core project.
Ok, let me start by pointing out that data contracts and data members are not directly related to WCF. Actually, these attributes reside in a namespace that has nothing to do with services directly...theyre rather related to serialization and it's just a matter of adding a reference to the required assembly...i think it's System.Runtime.Serialization. I don't see why you can't add a reference to this assembly in your project.
The second question related to "hiding" members...i dont think you have to many options here. If you decorate a property with the DataMember attribute it will be serialized with the data contract, so there's no way you can't "hide" it. At best, what you can do is not to decorate a property with the DataMember attribute, but in this case the property will not be serialized, in other words, it will be ignored during the serialization process.

Structure for loading different web references as a plug-in

We have developed an application in C# .NET that synchronises data (customers, orders) to a PHP e-commerce application using SOAP.
The WSDL of the PHP application is added as a .NET 2.0 web reference to our application, so the .NET Framework generates classes and functions to communicate with the SOAP web service.
For instance, we are able to send stock information like this:
catalogInventoryStockItemUpdateEntity stock = new catalogInventoryStockItemUpdateEntity();
stock.is_in_stock = 1;
stock.is_in_stockSpecified = true;
stock.qty = "10";
webserv.catalogInventoryStockItemUpdate(sessionid, itemcode, stock);
This works fine, however we are frequently running in situations where one of our customers has additional (non standard) fields defined in the WSDL and wants this fields to be used in the synchronisation.
Our current practice is to create a new branch of our code for this customer and update the web reference to use the specific WSDL of our customer.
To prevent us from getting a long unmaintanable list of branches of our software, I'm planning to do a complete overhaul of the structure of our application.
Now I am wondering what would be the best structure to handle this. I was thinking to put the web reference in it's own class and load this DLL dynamically, so if a customer has a non-standard WSDL we could create it's own class and load it as a 'plug-in' into our software. But the additional fields in (for instance) the catalogInventoryStockItemUpdate will then still not be available in the main part of our application.
Are there any tools that might help in achieving this? I would like to have one main application for synchronisation and put all customer specific mappings and references to the WSDL in a separate class/project.
First of all, for adding plugins support to your app you can use Microsoft Extensibility Framework (MEF). If you're constrained to using .NET 2.0, then there are other custom ways for discovering and loading up plugins (through separate app domains, or by loading them straight to the primary app domain).
As for the design, I would make each plugin:
Hold the service reference to it's particular web service instance.
Make any particular assignments or logic to that service. For example assign 10 to stock.qty.
Provide callbacks/events the application could use to interfere with the logic implemented in the plugin. For example, you could have the plugins expose an event called BeforeStockSubmitted and you could do some validation or checks in the app on the data being submitted to the service.
Your plugin host (the application, or a module of it) should:
Expose a consistent object model for all plugins. You should offer a certain degree of abstraction for all entities the plugins will work with (such as sessionId, stock, etc).
Data coming into the plugins should be abstracted as well. So you can have an IStockInfo interface in the host and each plugin should be constrained to provide their own implementation. The host can populate the common properties of these objects while the plugin takes care of the specific part.

Adding WCF Service References to multiple projects

A couple of very basic questions. I am new to WCF and I am building an application which has a Service Project, A Web Application project and a few Class library projects which I use for Business logic, etc.
I am hosting the WCF locally on my IIS and trying to add service references to the projects.
Question 1. When adding references, should I add a service reference to each project separately or is there a way I can share the same Service reference across the projects?
The reason I ask is because if I add separate references, each reference gets it own namespace, and when I have to pass the same object between the projects, I get an InvalidCastException because each ServiceClient has a different namespace.
Example -
Site.Business.XDataService.XDataServiceClient().GetItem()
is not the same as
Site.Web.XDataService.XDataServiceClient().GetItem()
Question 2. I specified the address of the local service in the class that implements the Service interface as below -
[ServiceBehavior(Namespace = "http://localhost:801/XDataService.svc", IncludeExceptionDetailInFaults = true)]
This doesn't seem right. If I move my code to a different/live environment, I would obviously have to change this part again and recompile. Where can I specify this (Web.Config?) so that I can change this address without having to rebuild my app?
Appreciate any kind of insight.
Thanks!
In answer to the first question, you can put the service reference in its own project and reference that project in all the other projects that need to access that service.
Basically all the service reference is is a lump of .NET code - namespace, class, etc.
Better yet (!) for a WCF service you also get an interface thrown in for free (more or less the same interface that you defined for your service) so you can do nice things in terms of dependency injection making testing etc easier.
First question - the service is just like any other code. For example, database access code. Should you put that in every project that needs to access your database? No - you should put it in a project which those other projects can reference.
As for your second question, you're specifying a namespace but I expect you think you're specifying a service endpoint address. The namespace is just like a C# code namespace - it essentially provides further identification and clarity in the event that you have multiple objects with the same name. Normally you'd use a namespace like http://mywebsite.com/MyService/VersionNumberIfRequired or similar.
The address itself is specified in configuration. The address will change depending on environment / deployment location - the namespace shouldn't.

Class Libraries, Silverlight and Webservices

I have a Silverlight Class Library that I want to use in both my Silverlight and my WebService project.
I am able to create and reference the Library in both projects without any problems, but when I try to use any of the classes in the Library on the Silerlight project, I get an ambiguous reference error between my Library and the Asmx Webservice (apparently, the silverlight project believes that the classes in the class library exist in the webservice).
How can I correct this issue? I have tried rebuilding and cleaning, but it does not seem to work. Can anyone help?
Sounds like the objects you are passing to Silverlight, via the WCF service, are the same objects in your class library. In that case the generated web-reference objects will be given the same names. Linking with the library will then give you 2 sets of objects with the same names.
If you install RIA services, once feature is the ability to share code between client and server by simply adding ".shared" in the class filenames before the extensions. ASMX services are so last century :)
if you don't want to learn the RIA services way of sharing objects across the great-web-divide (which I would recommend), you need to separate the data objects from the functionality you actually want to share client and server side.
To give more specific advice on your current set-up I would need to see more about how it is structured.
A technique you can use is aliasing your using statements:
using MyNameSpace = My.Name.Space;
using MyWebService = My.Web.Service;
Then access all of your objects with these aliases to remove the ambiguities.

Categories

Resources