Class Libraries, Silverlight and Webservices - c#

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.

Related

How to re-use a user control in two Silverlight client applications?

I'm kind of new to Silverlight and I have a solution which has one web project (webApp) that provides remote services and two client applications (client-1 and client-2) that uses these services.
I have created a complex user control in client-1 that view/edit an object retrieved from webApp and I want to re-use this control in client-2.
The problem is, when you reference the service from the client apps, the types are "locally-typed". For example, MyClass defined in the webApp becomes client-1.MyClass in client-1 app. Using exactly the same object (reference) in client-2 app, it is now of type client-2.MyClass
If I create a library to host my control, I will have to add a reference to the web services and I will have a third type, lib.MyClass. We all know that client-1.MyClass, client-2.MyClass and lib.MyClass are all exactly the same class that was generated from web.MyClass but I can't find a way around this problem.
I'm currently looking at sharing the source code of the user control in each client application and having pre-processor defines in each project so I can do this in my user control code file:
#if CLIENT-1
using Client-1.WebAppServiceReference
#end if
#if CLIENT-2
using Client-2.WebAppServiceReference
#end if
Then the method that uses the type MyClass are using the correct "local-type" in each client app. But I'm having problem since there is no pre-processor functionality in the xaml and there is a reference to the application's namespace there that I need to be conditional.
There's got a be an easier way of re-using controls accross silverlight projects, no?? There is no way I'm going to have two copies of the source files for this control, on in each project!!
Thanks!
There are a couple of options that allow you to use shared entity classes across Silverlight projects/WCF service proxies.
Use an RIA class library
Use a portable class library
If you create your DataContract classes with either of the above, and then reference the library from both your WCF and Silverlight client projects, then the auto-generated code will use a reference to those shared classes (rather than the locally auto-generated classes). This should allow you to re-use your Silverlight UserControls between projects.
The difference between the two approaches is this. If you use the first approach (RIA project), then when you create files named "SomeEntityClass.shared.cs", the ".shared" tells Visual Studio to place a copy of the file in a mirror Silverlight project. The second approach (PCL) is a newer approach -- it allows you to create class libraries that are capable of targeting multiple platforms (.Net, Silverlight, Windows Phone, ...), with a reduced set of core .NET libraries.
I suggest you to dissociate the XAML and graphical stuff from any of Business logics and the like. MVVM is a very good pattern to follow.
After that, you can reference your UserControl from second project with the very useful functionality of Visual Studio "Add as Link"
Here how you can do it :
For the underlying business, you can make it available for both project, and linking these 2 with it.
Hope it helps

How to create a WCF Data Services OData with with the Reflection Provider using model classes from different project?

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.

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.

Type Redefinition With WSE Web Service Import

Consider the following Visual Studio project structure
ProjectA.csproj
AClass.cs
ProjectB.csproj
References
ProjectA
Web References
AWebService
AWebService.csproj
References
ProjectA
ReturnAClassViaWebService.asmx
The issue occurs when ProjectB adds the web reference to AWebService and automatically generates all the proxy code for accessing AWebService including a new implementation of AClass. Since all of our other code needs to use the AClass defined in ProjectA, we're forced to convert the AWebService.AClass returned from the service into something we can use.
We're currently considering two solutions, neither of which are ideal.
Manually editing the generated Reference.cs to remove new definitions of AClass
Serializing AWebService.AClass to a stream then deserializing to ProjectA.AClass
Does anyone have any better solutions? This seems like something common enough for other developers to have experienced it.
Ideally we would like to have the proxy code generated in ProjectB to reference ProjectA.AClass rather than generating a whole new implementation.
Our environment is VS 2008 using .NET 2.0.
I have had the same problem that you are describing and I have tried both of the options you specify without being entirely happy about either of them.
The reason we both have this issue is at least partly because the shared-library-between-consumer-and-provider-of-a-web-service-solution is in violation of accepted patterns and practices for web service design. On the consumer side, it should be sufficient to know the interface published in the WSDL.
Still, if you are prepared to accept a tight coupling between your web service provider and web service consumer and you know for certain that your current client will never be replaced by a different client (which might not be capable of referencing the shared library), then I understand why the proposed solution seems like a neat way to structure your app. IMPORTANT NOTE: Can we really honestly answer yes to both of these questions? Probably not.
To recap:
The issue appears when you have classes (e.g. a strongly typed dataset) defined in some sort of shared library (used on both client and server).
Some of your shared classes are used in the interface defined by your web service.
When the web reference is added there are proxy classes defined (for your shared classes) within the web reference namespace.
Due to the different namespaces the proxy class and its actual counterpart in the shared library are incompatible.
Here are four solutions that can be tried if you want to go ahead with the shared library setup:
Don't. Use the proxy class on the client side. This is how it is intendend to be done. It works fine unless you simultaneously want to leverage aspects of the shared library that are not exposed by the web service WSDL.
Implement or use a provided copy/duplication feature of the class (e.g. you could try to Merge() one strongly typed dataset into another). A Cast is obviosuly not possible, and the copy option is usually not a very good solution either since it tends to have undesirable side-effects. E.g. When you Merge a dataset into another, all the rows in the target dataset will be labeled as 'changed'. This could be resurrected with AcceptChanges(), but what if a couple of the received rows were actually changed.
Serialize everything - except for elementary data types - into strings (and back again on the consumer side). Loss of type safety is one important weakness of this approach.
Remove the explicit declaration of the shared class in Reference.cs and strip the namespace from the shared class wherever it is mentioned within Reference.cs. This is probably the best option. You get what you really wanted. The shared class is returned by the web service. The only irritating drawback with this solution is that your modifications to the reference.cs file is lost whenever you update your web reference. Trust me: It can be seriously annoying.
Here is a link to a similar discussion:
You can reuse existing referenced types between the client and service by clicking on the 'Advanced' button on the 'Add Service Reference' form. Make sure the 'Reuse types in referenced assemblies' checkbox is checked and when the service client is generated it should reuse all types from project A.
In past versions this has not always worked correctly and I've had to explicitly select the shared type assemblies by selecting the 'Reuse types in specified referenced assemblies' option and then checking the appropriate assemblies in the list box. However, I just tested this with VS 2008 SP1 and it appears to work as expected. Obviously, you need to make sure that the types that are being used by the service and client projects are both from project A.
Hope that this helps.
We encountered a similar problem with one of our projects. Because we had several dependencies, we ended up creating a circular reference because project 1 required objects from project 2, but project 2 could not be build before project 3, which relied on project 1 to be build.
To solve this problem, we extracted all the public standalone classes from both projects and placed them inside a single librarie. In the end we created something like this:
Framework.Objects
Framework.Interface
Framework.Implementation
WebService
The WebService would be linked to all projects in our case, whereas external parties would only be linking to the objects and interface classes to work with. The actuall implementation was coupled at runtime through reflection.
Hope this helps

One entity shared across two web services?

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.

Categories

Resources