Label Cloud

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

Friday, January 25, 2008

WCFTestClient - a testing utility from Visual Studio 2008

I stumbled upon an excellent utility for WCF Testing that comes with Visual Studio 2008 - WCFTestClient.

The tool is an simple way to test WCF clients HTTP and TCP bindings. Some things are not supported, however, for basic WCF Testing, this definitely beats the old ASMX test page.

Note: Also check out the WCFSvcHost utility from Visual Studio to host an arbitrary WCF Service.


Share/Save/Bookmark

Monday, January 07, 2008

Fixing WCF/WPF VS 2005 Extensions installation after installing VS 2008 or .NET 3.0 SP1

I've encountered a problem trying fix the WCF / WPF Visual Studio 2005 Integration components after I've installed Visual Studio 2008.

Installing a VS 2008 will install .NET 3.0 SP1 and remove the installation of .NET 3.0. When trying to install the WCF / WPF Extension, installation display's a message

Setup has detected that a prerequisite is missing. To use Visual Studio 2005 extensions for .NET Framework 3.0 (WCF & WPF), November 2006 CTP you must have the .NET Framework 3.0 runtime installed. Please install the .NET Framework 3.0 runtime and restart setup

You really can't install .NET 3.0 since a newer version (.NET 3.0 SP1) is already installed.

I found a solution on the MS Forums http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2550726&SiteID=1

It involves either going creating a registry key to full the installers into thinking that SP1 is installed. To fix the issue, add the following value to the registry:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{15095BF3-A3D7-4DDF-B193-3A496881E003}] "DisplayName"="Microsoft .NET Framework 3.0"

Thanks Erich for the solution.

Note: I got a comment that this can also be forced using command line: msiexec /i vsextwfx.msi WRC_INSTALLED_OVERRIDE=1

Thanks


Share/Save/Bookmark

Wednesday, December 05, 2007

Creating a ClickOnce Smart Client CAB Based (SCSF) application with Environment Overrides

My application is distributed via ClickOnce and a requirement is to be able to provide endpoint overrides for multiple environments. Here's what was done to create the solution


Smart Client Software Factory includes a service called EndpointCatalog. It allow for easy management of endpoints with environment overrides. Start by adding a Microsoft.Practices.SmartClient.EndpointCatalog.dll as a reference to Infrastructure.Module. Then open ModuleController class in and register the EndpointCatalog service.

private void AddServices()
{
IEndpointCatalog catalog = WorkItem.RootWorkItem.Services.Get<IEndpointCatalog>(false);
if (catalog == null)
{
IEndpointCatalogFactory catalogFactory =
new EndpointCatalogFactory("Endpoints");

catalog = catalogFactory.CreateCatalog();
WorkItem.RootWorkItem.Services.Add<IEndpointCatalog>(catalog);
}

This will read the endpoint catalog from the application.config file , section Endpoints. Here is a partial app.config

<configSections>
<section name="Endpoints" type="Microsoft.Practices.SmartClient.EndpointCatalog.Configuration.EndpointSection, Microsoft.Practices.SmartClient.EndpointCatalog" />
</configSections>

<Endpoints>
<EndpointItems>
<add Name="DataService.DataClient"
Address="http://server/DataService.svc"
UserName="default-user-name" Password="default-password" Domain="default-domain">
<NetworkItems>
<add Name="QA" Address="http://qa.server/DataService.svc"/>
<add Name="UAT" Address="http://uat.server/DataService.svc"/>
</NetworkItems>
</add>
</EndpointItems>
</Endpoints>

The endpoints section defines an endpoint, and an override for each environment. The catalog will return the override if it exists, or the original entry if it does not.

To create the WCF client, I created the following function.

T CreateWCFClient<T, Ti>()
where T : ClientBase<Ti>, new()
where Ti : class
{
try
{
T client = new T();
if (endpointCatalog.EndpointExists(typeof(T).FullName))
{
client.Endpoint.Address = new EndpointAddress
(endpointCatalog.GetAddressForEndpoint(typeof(T).FullName, Environment));
}
return client;
}
catch (Exception)
{
throw;
}
}

Add the required service to the module that will hold the function and you are almost done. The request to create the client is as follows.

_DataWebService = CreateWCFClient<DataService.DataClient, DataService.IDataClient>();

Please comment for any questions, I'll try to clarify


Share/Save/Bookmark

Saturday, October 13, 2007

Providing multiple endpoints for the WCF service

I had to implement compression for an internal WCF service. A requirement however is to make sure that older version of the service is left as is. To achieve that we've added another endpoint to the an existing binding

Here's the original Configuration File for the server.

<services> <service name="Repositories.Clients" behaviorConfiguration="DebugBehavior"> <endpoint name="Clients" contract="IClients" binding="basicHttpBinding" /> </service> <services> <behaviors> <serviceBehaviors> <behavior name="DebugBehavior"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> </behaviors>

The URL for the service is http://hostname/Clients.svc

Here's the new file

<services> <service name="Repositories.Clients" behaviorConfiguration="DebugBehavior"> <endpoint name="Clients" contract="IClients" binding="basicHttpBinding" /> <endpoint name="ClientsCompressed" contract="IClients" bindingConfiguration="compressedConfiguration" binding="customBinding" address="compressed"/> </service> <services> <bindings> <customBinding> <binding name="compressedConfiguration"> <compression compressionMode="GZip" compressionLevel="Normal"/> <httpTransport/> </binding> </customBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="DebugBehavior"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> </behaviors>

The new URL for the service is http://hostname/Clients.svcc/compressed

The old service works just like before. But the new one requires compressed data. It is serviced by a completely separate binding and has independent configuration.

 


You can follow the same above example to specify multiple client endpoints as well. However, if multiple endpoints exist, the WCF Proxy has to be created by specifying an endpoint name.

 

localhost.Clients1Client client = new localhost.Clients1Client("compressed");

Technorati Tags: , ,


Share/Save/Bookmark

Monday, March 05, 2007

Update to Smart Client Software Factory

Blaine Wastell is writing about a soon to come out April Update to Smart Client Software Factory. The new functionality is extremely interesting:

  • WPF Interoperability
  • Offline Application Block (this was released a while back, but I didn't see support for it recently)
  • WCF Support
  • Possible support for WWF (Windows Workflow). This is 2nd priority, but that means it might be released in the future updates, if not in the April update.


Share/Save/Bookmark

Thursday, November 16, 2006

WCF - Processing untyped messages from MSMQ binding

Now that .NET 3.0 is finally released, I am putting in some hours to see how it can be implemented in our infrastructure. Up front the power and flexibility of the framework is a bit overwhelming, however, the tools that are included are great. For example Service Configuration Editor has a great way to specify every setting required and optional for setting up WCF communication.

One of the components that I was looking to replace is a MSMQ Message Processing application. Basically it is a custom written MSMQ Trigger service. Well.. here goes.

WCF includes a binding for interconnecting with non-WCF MSMQ implementations. I've created the final prototype from the basic service sample, and created a ServiceContract interface and implementation class

[ServiceContract()]
public interface IMessageProcessor
{
   [OperationContract(IsOneWay = true)]
   void ProcessMessage(MsmqMessage<Stream> msg);
}

public class MessageProcessor : IMessageProcessor
{
   public void ProcessMessage(MsmqMessage<Stream> msg)
   {
      using (StreamReader sr = new StreamReader(msg.Body))
      {
         MessageBox.Show("Hello: " + sr.ReadToEnd());
         sr.Close();
      }
   }
}

Then added created a main form, and added start/stop events
 
internal static ServiceHost myServiceHost = null;
internal static void StartService()
{
   // Instantiate new ServiceHost
   myServiceHost = new ServiceHost(typeof(MessageProcessor));
   myServiceHost.Open();
}
internal static void StopService()
{
   // Call StopService from your shutdown logic (i.e. dispose method)
   if (myServiceHost.State != CommunicationState.Closed)
   myServiceHost.Close();
}
private void MainForm_Load(object sender, EventArgs e)
{
   StartService();
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
   StopService();
}

The next step is to setup the app.config configuration file.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
   <system.serviceModel>
      <behaviors>
         <serviceBehaviors>
            <behavior name="Throttling">
               <serviceThrottling maxConcurrentCalls="2" />
            </behavior>
         </serviceBehaviors>
      </behaviors>
      <bindings>
         <msmqIntegrationBinding>
         <binding name="NewBinding0" exactlyOnce="false" serializationFormat="Stream" />
         </msmqIntegrationBinding>
      </bindings>
      <services>
         <service behaviorConfiguration="Throttling" name="WCFMQListener.MessageProcessor">
            <endpoint address="msmq.formatname:DIRECT=OS:.\private$\testqueue" binding="msmqIntegrationBinding" bindingConfiguration="NewBinding0" contract="WCFMQListener.IMessageProcessor" />
         </service>
      </services>
   </system.serviceModel>
</configuration>

The most time I've spent was to figure out how to read the non-xml formatted message. The key is to declare the method as

void ProcessMessage(MsmqMessage<Stream> msg);

and to adjust binding in the configuration file

serializationFormat="Stream"

The message can be read just as easily as a binary array.


Share/Save/Bookmark
Directory of Computers/Tech Blogs