|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionIn our second article of the series "Exploring Windows Communication Foundation", we explore the customization of the service and working with faults and errors. Specifically, we look at the following:
Hosting WCF Service in IIS/ASP.NETTo host a service in IIS/ASP.NET, we need to do the following:
If you have installed IIS and .NET Framework 2.0 Redistributable in this order, you do not need to register ASP.NET Runtime. You can check if ASP.NET Runtime is registered with a website or not by checking the properties of the website as shown below:
If the ASP.NET Runtime is not registered with IIS, execute the following on the commandline for the registration: %windir%\Microsoft.Net\Framework\v2.0.50727\aspnet_regiis.exe -i
To register the WCF with IIS and ASP.NET 2.0, execute the following on the commandline: ServiceModelReg.exe -i -x
The application The next step is to create an ASP.Net Website. Let's call it
Incase you do not find the template for adding a new WCF service, don't be disheartened. You can simply add a new text file and name it Open the <%@ ServiceHost Debug="true" Service="ShoppingCartLibrary.ShoppingCartImpl" %>
Create the folder Modify the configuration file <?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="HttpGetBehaviour">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="ShoppingCartLibrary.ShoppingCartImpl"
behaviorConfiguration="HttpGetBehaviour">
<endpoint binding="mexHttpBinding"
contract="ShoppingCartLibrary.IShoppingCartService"
address=""/>
</service>
</services>
</system.serviceModel>
</configuration>
Hurray! The service has been deployed. Browse to the location
In that case (or uncompiled output), execute the following on the commandline: ServiceModelReg.exe -s:W3SVC/1/ROOT/ShoppingCart
Refresh the page in browser. Now, you should be able to see an output as shown below:
Updating the clientThe next step is to update the client (proxy class and configuration) to connect to our new service. Ah! We don't need to regenerate everything. Open the client application configuration file and modify the endpoint-address (in the section The client should give identical results as what we got while working with self-hosted service (created in previous article). Service CustomizationLet us now look at important aspect of decoupling the WCF contract names and .Net names (data-types and/or parameters). In general, we do not want to have dependency on the field/parameter/data-type names that we choose in .Net and what we publish to the world. Not only it may put under risk the application but also may be mandatory. Say, for example, if we need to have a parameter by the name Service Contract NameThe first requirement that we look at it isolating the service name and the namespace-URI to which it belongs, and the name of the interface. The Update the interface using System;
using System.ServiceModel;
namespace ShoppingCartLibrary
{
[ServiceContract(Name="Shopping-Cart-Service",
Namespace="http://www.edujinionline.com/ns/wcf/tutorial/scart")]
public interface IShoppingCartService
{
[OperationContract]
bool CheckUserExists(string username);
[OperationContract]
DateTime? GetLastTransactionTime(string username);
}
}
Starting the hosting application that we created in the previous article. Browse to the location Also notice that the new name of the portType is now However, if we need to change the name of the service (in service section of WSDL) and the namespace-URI of the same, we need to change the service-behaviour rather than the contract details. The default value of the same are the name of the implementation class and http://tempuri.org. Let us update them to We shall make use of the Update the class using System;
using System.ServiceModel;
namespace ShoppingCartLibrary
{
[ServiceBehavior(Name="Shopping-Cart-Impl",
Namespace="http://www.edujinionline.com/ns/wcf/tutorials/scart/impl")]
public class ShoppingCartImpl : IShoppingCartService
{
//Other code not shown
}
}
Operation NamesSimilarly, to change the value of the operation, one can make use of using System;
using System.ServiceModel;
namespace ShoppingCartLibrary
{
[ServiceContract(Name="Shopping-Cart-Service",
Namespace="http://www.edujinionline.com/ns/wcf/tutorial/scart")]
public interface IShoppingCartService
{
[OperationContract(Name="UserExists")]
bool CheckUserExists(string username);
[OperationContract(Name="LastTransactionTime")]
DateTime? GetLastTransactionTime(string username);
}
}
Action URIs for input and output messagesLaunch the hosting application and browse to The properties using System;
using System.ServiceModel;
namespace ShoppingCartLibrary
{
[ServiceContract(Name="Shopping-Cart-Service",
Namespace="http://www.myurl.com/scart")]
public interface IShoppingCartService
{
[OperationContract(Name="UserExists",
Action="http://www.myurl.com/scart/actions/UserExists",
ReplyAction="http://www.myurl.com/scart/actions/UserExistsOut")]
bool CheckUserExists(string username);
[OperationContract(Name="LastTransactionTime",
Action="http://www.myurl.com/scart/actions/LastTranactionTime",
ReplyAction="www.myurl.com/scart/actions/LastTranactionTimeOut")]
DateTime? GetLastTransactionTime(string username);
}
}
Similarly, the order in which the operations should appear in the WSDL can be defined by setting the property Parameter NamesLet us say that our shopping cart works with email address as far the interface to the world is concerned. Internally, we would like to refer to it as username, like we have been doing so far.
using System;
using System.ServiceModel;
namespace ShoppingCartLibrary
{
[ServiceContract(Name="Shopping-Cart-Service",
Namespace="http://www.myurl.com/scart")]
public interface IShoppingCartService
{
[OperationContract(Name="UserExists",
Action="http://www.myurl.com/scart/actions/UserExists",
ReplyAction="http://www.myurl.com/scart/actions/UserExistsOut")]
[return: MessageParameter(Name="ExistsInfo")]
bool CheckUserExists(
[MessageParameter(Name="email")] string username);
[OperationContract(Name="LastTransactionTime",
Action="http://www.myurl.com/scart/actions/LastTranactionTime",
ReplyAction="http://www.myurl.com/scart/actions/LastTranactionTimeOut")]
[return: MessageParameter(Name="TimeInfo")]
DateTime? GetLastTransactionTime(
[MessageParameter(Name="email")] string username);
}
}
With all these changes, we need to regenerate the proxy-client (using Now, before proceeding ahead with any transaction, let us enable tracing to have a look at the message being transported. Update the application configuration file for the host to have the following entries: <configuration>
<system.diagnostics>
<sources>
<source name="System.ServiceModel.MessageLogging"
switchValue="Verbose">
<listeners>
<add name="xml"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="..\..\..\wcf_scart.svclog" />
</listeners>
</source>
</sources>
<trace autoflush="true" />
</system.diagnostics>
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" maxMessagesToLog="300"
logMessagesAtServiceLevel="false"
logMalformedMessages="true"
logMessagesAtTransportLevel="true" />
</diagnostics>
< ... >
</system.ServiceModel>
</configuration>
Update the client application to as shown below (code in bold are the updates done): using System;
namespace ShoppingCartConsumer
{
public class MainClass
{
public static void Main(string[] args)
{
ShoppingCartServiceClient client = new ShoppingCartServiceClient();
string[] users = new string[] { "gvaish", "edujini", "other" };
foreach(string user in users)
{
Console.WriteLine("User: {0}", user);
Console.WriteLine("\tExists: {0}", client.UserExists(user));
DateTime? time = client.LastTransactionTime(user);
if(time.HasValue)
{
Console.WriteLine("\tLast Transaction: {0}", time.Value);
} else
{
Console.WriteLine("\tNever transacted");
}
}
Console.WriteLine();
}
}
}
Notice that there no longer exists the methods Launch the
SummaryWe looked at how to host the service in IIS/ASP.Net. We also looked at how we can isolate the .Net parameter and operation paramter names. That's it for now. It close to midnight and I would discuss about the faults and error-handling in WCF in the next article. Contact
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||