次の方法で共有


Web Services and namespaces (or WCF?)

You might have encountered following situation:
1. You have created class library “MyLibrary” and it contains following class:

 12345678
 namespace MyLibrary{  public class Employee  {    public string FirstName;    public string LastName;  }}

2. You have created Web Service “MyWeb” using following VS template:

Web Service project

  - It references “MyLibrary”

  - It contains following method:

 12345678
 public class MyWeb : System.Web.Services.WebService{  [WebMethod]  public void AddNewEmployee(MyLibrary.Employee employee)  {    // TODO: implement  }}

3. Finally you create Windows Forms application “My Win App”:

  - You “Add Web Reference” to “MyWeb” and you name it “WebServices”

  - You write following code to use that web service:

 12345
 WebServices.Employee employee = new WebServices.Employee();employee.FirstName = "John";employee.LastName = "Doe";WebServices.MyWeb myWeb = new WebServices.MyWeb();myWeb.AddNewEmployee(employee);

4. You run your application and all is fine.

5. Later you notice that you need to add reference to your “MyLibrary” into your “My Win App”

(There could be many reasons for this. For example you want to use same business logic that web service uses etc.)

6. You add following code to you “My Win App”:

 123
 MyLibrary.Employee employee2 = new MyLibrary.Employee();MyLibrary.EmployeeManager employeeManager = new MyLibrary.EmployeeManager();employeeManager.AddNewEmployee(employee2);

7. Code works fine but then you notice that you actually have the same class from two different namespaces. What if you try to mix and match them (and sometimes you just have to do that)? Let’s see what happens:

 123
 WebServices.Employee employee = new WebServices.Employee();MyLibrary.EmployeeManager employeeManager = new MyLibrary.EmployeeManager();employeeManager.AddNewEmployee(employee);

8. When you try to compile your application and you’ll receive following error:

VS compile error  Error    11    The best overloaded method match for 'MyLibrary.EmployeeManager.AddNewEmployee(MyLibrary.Employee)' has some invalid arguments    C:\<path>\MyWinApp\MainForm.cs    41    1    MyWinApp

Error    12    Argument '1': cannot convert from 'MyWinApp.WebServices.Employee' to 'MyLibrary.Employee'    C:\<path>\MyWinApp\MainForm.cs    41    32    MyWinApp

9. You open up the generated proxy code:

Reference

10. You locate the code where Employee is defined and comment that part. And then you compile again with following results:

Error 11 The type or namespace name 'Employee' could not be found (are you missing a using directive or an assembly reference?) C:\<path>\MyWinApp\Web References\WebServices\Reference.cs 82 36 MyWinApp

11. You fix that by resolving the missing type:

VS Resolve

12. You compile and you’re happy right (obviously you need to modify also all WebServices.Employee types to MyLibrary.Employee types)?

Well you might be happy since now your code works... BUT you have manually edited generated file which will be re-generated every time you do “Update Web Reference” from Visual Studio and you’ll lose you modifications. And that’s not nice.

If this would be question for me I would give you following answer (you might find different opinions on this one): Go to the WCF route instead :-) If Windows Communication Foundation (WCF) is something new to you I think you should check these out and find more information on the web: Overview of WCF from Wikipedia and Windows Communication Foundation home on MSDN.

I’m going to run through this same example with WCF way and then we can (hopefully) see why it fits like good glove.

1. Create new WCF project called “MyWcf” using following VS template:

WCF 1

2. Add reference to “MyLibrary”

3. Delete IService1.cs and Service1.svc from your newly created project.

4. Add new item “MyWcfService.svc” (using WCF Service template)

5. Modify “IMyWcfService.cs” file:

 123456789101112
 using System.ServiceModel;using MyLibrary;namespace MyWcf{  [ServiceContract]  public interface IMyWcfService  {    [OperationContract]    void AddNewEmployee(Employee employee);  }}

6. Modify “MyWcfService.cs” file:

 12345678910111213
 using System;using MyLibrary;namespace MyWcf{  public class MyWcfService : IMyWcfService  {    public void AddNewEmployee(Employee employee)    {      // TODO: implement    }  }}

7. Open up “web.config” and modify the system.serviceModel section as follows:

 1234567891011121314151617181920
 <system.serviceModel> <services>  <service behaviorConfiguration="MyWcf.MyWcfServiceBehavior" name="MyWcf.MyWcfService">   <endpoint address="" binding="basicHttpBinding" contract="MyWcf.IMyWcfService">    <identity>     <dns value="localhost" />    </identity>   </endpoint>   <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />  </service> </services> <behaviors>  <serviceBehaviors>   <behavior name="MyWcf.MyWcfServiceBehavior">    <serviceMetadata httpGetEnabled="true" />    <serviceDebug includeExceptionDetailInFaults="false" />   </behavior>  </serviceBehaviors> </behaviors></system.serviceModel>

(you might notice that most important part is the bindingwhat I have changed to be basicHttpBinding)

8. Go back to your “My Win App” project.

  - Remove “WebServices” web references

  - Add new “Service Reference” to your newly created WCF Service and name it “WcfServices”

  - Verify that you have “Reuse types in referenced assemblies” checked in settings (you can see them if you click Advanced... button from the “Add Service Reference” dialog):

WCF 2 

9. Modify your code to use this new service:

 12345
 MyLibrary.Employee employee = new Employee();employee.FirstName = "John";employee.LastName = "Doe";WcfServices.MyWcfServiceClient myWcf = new MyWinApp.WcfServices.MyWcfServiceClient();myWcf.AddNewEmployee(employee);

10. Enjoy one of the benefits of WCF :-)

This is just one of the many benefits that WCF over the “good old ASP.NET Web Services”. So if you’re interested then you should start looking more information on the web.

Anyways... Happy hacking!

J

Comments

  • Anonymous
    November 09, 2008
    The comment has been removed

  • Anonymous
    June 23, 2009
    i could not change binding to basicHttpBinding. when i change it, i can not add the service reference to the client application. while it's selected to be reuse types in all reference assemblies, i still have service assembly type instead of local types. what should i do?

  • Anonymous
    December 09, 2010
    Nice way to resolve this issue, I was always wondering how can I solve this issue.