Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Tuesday, January 31, 2012

WCF Test Client Error

When starting to debug a new WCF service I received the following error message:

“The contract ‘IMetatdataExchange’ in client configuration does not match the name in service contract, or there is no valid method in this contract.”

image

I had added my MEX endpoint in the web.config and was able to review the service WSDL through a browser, so I was really not sure why I was getting this. As it turns out, this error message is caused by an entry in the machine.config for an endpoint declaration defined like this:

<endpoint address="" binding="netTcpRelayBinding" contract="IMetadataExchange" name="sb" />

I’ve commented it out for now and the WCF Test Client is now able to properly interrogate the service metadata without giving me an error.

After a bit of Google’ing this error, I found this explanation from Joel C on StackOverflow.com. Looks like at some point an installation for the .NET Service SDK (which I don’t remember installing) updated the machine.config with that information.

For now, it works having removed it.

Wednesday, January 18, 2012

Creating a Dependency Injected WCF Data Service

In this post, I’ll explain how to decouple your WCF data service from a specific data context. This is useful in many ways including changing out your context implementation at runtime or mocking out your context for testing purposes. The example code will use MEF (Managed Extensibility Framework), but any dependency injection framework, service locator implementation, or factory pattern could be used.

Getting Started

The first thing you will need to get started is an implementation of DbContext. I’ve chosen to go with a code first approach in this example because it gives me explicit control over the code in the context. Entity Framework 4.1, which is available as a Nuget package, provides a simple, purpose-driven API, which allows me to create a new DbContext and specify the entity types that it is responsible for in just a few lines of code. The base class and EF4.1 plumbing does all the hard work.

public class PersonContext : DbContext
{
public IDbSet<Person> People { get; set; }
public IDbSet<Address> Addresses { get; set; }
}

Figure 1: Basic PersonContext implementation

This implementation satisfies the most basic requirements of EF4.1 for a DbContext, but as you’ll see as we go along, we’ll want to flesh it out a bit more in order to support MEF’s requirements.


Give Your DbContext an Interface


Uncle Bob Martin’s SOLID object oriented principles is a must-read for all programmers. The ‘D’ in SOLID is for Dependency Inversion. In a nutshell, dependencies between objects should be based on abstractions not concretions.  Our next step is to create an interface that will represent our DbContext.

 

public interface IDbContext : IDisposable
{
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
}
Figure 2: IDbContext interface

 

Initializing Your Context


The EF4.1 DbContext class can take a connection string in as a constructor parameter. For simple cases, this might be enough for you. However, if your context requires additional information to operate properly, you may want create a configuration class that you can inject into your context through its constructor. I’ve take this approach because it allows for greater flexibility in initialization of the context.


[Export]
public class DbContextConfiguration
{
public string Name { get; set; }
public string ConnectionString { get; set; }
}

Figure 3: DbContextConfiguration needed to initialize your DbContext

 

[ImportingConstructor]
public PersonContext([Import("PersonContextConfiguration", typeof(DbContextConfiguration))] DbContextConfiguration configuration)
: base(configuration.ConnectionString)
{
_configuration = configuration;
}
Figure 4: PersonContext constructor

 

The first thing you’ll notice in the code above are the [Export], [ImportingConstructor], and [Import] attributes that are applied to the DbContextConfiguration class and PersonContext constructor. These are MEF attributes, which are used to support the dependency injection pattern. MEF will handle auto-magically wiring up the dependencies through a call to ComposeParts(). If you are new to MEF or unfamiliar with how it works, here are a couple of useful links to get you started.

 



 

Creating Your WCF Data Service


Writing a WCF data service couldn’t be easier. In a matter of a few mouse clicks, you can be serving up REST-based data. Microsoft has dramatically reduced the effort required to implement a service by providing a rich API that provides a lot of functionality under the covers.


image


Figure 5: Add New Item


Adding a new WCF Data Service through the Add New Item dialog results in an entry point to that API via the DataService<T> class.



   1: public class PersonDataService : DataService< /* TODO: put your data source class name here */ >
   2:     {
   3:         // This method is called only once to initialize service-wide policies.
   4:         public static void InitializeService(DataServiceConfiguration config)
   5:         {
   6:             // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
   7:             // Examples:
   8:             // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead);
   9:             // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
  10:             config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
  11:         }
  12:     }

Figure 6: Boilerplate data service code


Simply replace the boilerplate TODO between the generic template brackets with a class that extends DbContext and you’re practically good to go. They even provide code snippets via comments that serve as placeholders for configuration changes that you can use to set access rules for the entity sets exposed by your DbContext.


*Note: in my example above, the DataServiceProtocolVersion.V3 is implemented in the October 2011 CTP release for data services. I began using it in order to integrate with the Entity Framework 4.1 DbContext API.


In our case, we will declare the data service this way:


public class PersonDataService : DataService<IDbContext> {…}


Override CreateDataSource


Next is the final piece of the puzzle. The DataService class provides a convenient way to control the instantiation of your service’s data source dependency. Namely - we will override the CreateDataSource method with an implementation such as this:


protected override IDbContext CreateDataSource()
{
context = compositionContainer.GetExportedValue<IDbContext>();
return context;
}

Figure 7: CreateDataSource implementation

 

Your implementation may differ, but essentially you want to use your MEF composition container, service locator, or other factory implementation in order to get an instance of your context based on the interface type. MEF has numerous ways for you to resolve this dependency.

 

A critical concern for your code in this area is to handle the multiplicity of dependencies you may find in your container. In a future post, I’ll demonstrate how to specify metadata to filter the results of your composition request.

 

Conclusion


Creating a loosely coupled design can sometimes be a challenge. In the case of WCF Data Services, Microsoft had the foresight to make this chore easier. Through abstraction of your data context, use of an extensibility framework like MEF, service locator or factory implementation, and a little glue code, you can decouple the service and context and reap the rewards of runtime composition and increased testability.

 

Wednesday, September 8, 2010

Manually Deploying a WCF Service to IIS

I recently downloaded the WCF and WF samples to begin looking at the Federation sample. The topic of federated security in WCF is an interesting one and I will write about my experience with it in a future post; however, I wanted to address a more basic situation that I ran into while working with the sample project.

I opened the solution in Visual Studio 2010 and compiled it. After successfully compiling, I attempted to run the client project, which is configured as the startup project. The app started, but the browse books capability failed because I had not deployed the web service that the application required in order to get data. * In the interest of disclosure, I did not follow the recommendation of using the setup.bat to create and deploy the web site and related applications to host the STS and app services because I wanted control over where/how they were created.

The information in this post is admittedly pretty basic, but in my experience these simple steps are sometimes missed making it impossible to test your service. Therefore, in this post I will list the simple steps needed to publish/deploy a WCF service to IIS.

If you need more information on WCF, just check out the Beginner’s Guide to Windows Communication Foundation. There you can find a lot of useful information on writing WCF services and exploring the various hosting options available to you.

Create a New Web Site

After writing your service or compiling the sample you’re working with, you need a web site to host it. Assuming you have a working service implementation…

1.) Click Start\Run and type ‘inetmgr’ (assuming you already have IIS installed)

2) Right click sites, and add a new site. In my case, I created the BookStore site. I created the physical path C:\inetpub\wwwroot\Bookstore

3) I then created a subdirectory for web services. C:\inetpub\wwwroot\Bookstore\Services and a bin folder to put the binaries in that you just compiled. You should end up with a directory structure like this: C:\inetpub\wwwroot\<yoursite>\Services\bin.

Copy the Content to the New Site

4) Copy the DLLs from your services bin\debug or bin\release folder to the …\<yoursite>\Services\bin folder.

5) Copy the web service’s .svc and web.config files into the …\<yoursite>\Services folder. If your service has any additional files that it needs to function, copy them to that folder as well. The Book Store example needed a .txt file for its data.

Create a New Application to Host the Service

6) In the IIS Manager, create a new application for your services folder. Do this by right-clicking the Services folder and select, “Convert to Application”. Select your newly created Services folder for the physical folder and click OK. Make note of the application pool that you selected.

7) Change the application pool’s advanced settings to select the .NET Framework 4.0 (assuming you’re using 4.0 – if not be sure the right version of .NET for you is selected).

Set the ACL on Your Physical File Folders

8) Grant access to the application pool identity to your file folder. The identity that you select will be IIS AppPool\<AppPoolName>.In my case it was IIS AppPool\BookStore. Be sure to grant it Read & execute, List folder contents, and Read.

If you happen to miss this step, IIS cannot load your service assemblies.


 

9) That’s it! To test your service, you should be able to select the .svc file in the IIS Manager and click Browse and get a screen that describes your service.

Good luck!

/imapcgeek

Wednesday, July 28, 2010

Troubleshooting a Failed Deployment of WCF Services on IIS7

In this blog post I will describe a problem that I recently experienced while developing a new WCF service and deploying it to a local IIS installation on Windows 7. The details of the service itself are unimportant; rather, the specific problems are related to the deployment of the service and with the setup and installation of IIS.

When attempting to browse to the newly deployed service (which was nothing more than a stub at this point), I experienced two problems. First, there was no handler mapping for the .svc extension. After I rectified that, I received the following error:

HTTP Error 500.21 – Internal Server Error
Handler “svc-Integrated” has a bad module “ManagedPipelineHandler” in its module list

According to the error page that was presented, the most likely causes were:

  1. Managed handler is used; however, ASP.NET is not installed or is not installed completely.
  2. There is a typographical error in the configuration for the handler module list.

How I got here:

  1. I installed the Internet Information Services through the Control Panel \ Windows Features dialog.

  2. I then manually created a new Application Pool to host the new services web site.

  3. From there I created a new Web Site to host the service.

  4. Last, I set my publication settings in Visual Studio to push the service and its implementation to the newly created website. Executing the publish from the IDE all things went well.

 

When I browsed to the service in the IIS Manager, I received the dreaded error above.

The root cause of this is mainly a timing issue. Depending on the order in which you install .NET and IIS, then the WCF and ASP.NET handlers and related modules will not be properly configured. Fortunately, resolving the issue is fairly straightforward.

  1. To resolve the problem with a lack of a .svc handler mapping, run the following:
    “%windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe –i”

    or if you are running with .NET 4, then the path is:
    “%windir%\Microsoft.NET\Framework\v4.0.30319\ServiceModelReg.exe –i”

    * Note that if you’re running on a 64-bit O/S you will need to change the path to use “Framework64” instead of “Framework”
  2. Lastly, to resolve the error above, you need to re-run the ASP.NET registration using this command:
    “%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe –i”

Once you’ve done that, you should be able to then access your WCF service. Hope this helps resolve this for you if you run into a similar situation.

del.icio.us Tags: ,,,