WCF Architecture, and Evolution, Version - c#

This question is around how to architect WCF services to make it easy to evolve over time.
Its difficult to get the depth of response to this without describing the problem.
Background
I am developing a large system of WCF services and clients.
The server side is "easy" to update as there are only 10 servers in question running this code.
The clients are very difficult to update, despite the high degree of automation, at 300,000+ WCF clients, updates are something that will always take time, and only achieves a high update success rate over a period of two to three weeks.
Data Contracts
[DataContract]
public class MyContract
{
[DataMember]
public int Identity {get; set;}
[DataMember]
public string Name {get; set;}
// More members
}
The DataContract is difficult to initialise and has a standard MyContractFactory class to initialise obtain the appropriate instance for your machine.
public class static MyContractFactory
{
public static MyContract GetMyContract()
{
// Complex implementation
}
}
ServiceContracts
The DataContract is very common across a range of web services.
namespace MyPrefix.WebServicve1
{
[ServiceContract]
public class IMyInterface1
{
[OperationContract]
public void DoSomethingWithMyContract(MyContract data);
}
[ServiceContract]
public class IMyInterface2
{
[OperationContract]
public void DoSomethingDifferentWithMyContract(MyContract data);
}
}
Client
My client is plugin based with plugins running in either separate processes or app domains depending on the level of trust we have in that plugin.
Implementation 1
My initial implementation of this (default WCF) ended up with the DataContract in one assembly, ServiceContract, and implementation in its own assembly.
The clients ended up with a very ugly,
MyWebService1.MyContract
MyWebService2.MyContract
With a copy and paste of the MyContractFactory in nearly every plugin. Whilst the DataContract was the same, the fact that the clients did not include the DataContract assembly meant that it appeared under different namespaces as different objects.
Implementation 2
The clients now include the DataContract assembly, ServiceContracts are in a separate assembly to the service implementation, clients may include some of the ServiceContract assemblies if it will aid with code reuse (no more copy and paste).
Question
With the second implementation I am now facing the difficulty of, how do I update my DataContract and ServiceContracts?
Do I update the same assembly and increment the version number? How do I preserve backwards compatibility whilst all the clients upgrade? Breaking the clients until they update is not acceptable.
Do I create a new assembly with a class that extends MyDataContract, new methods that accept the new type under a new ServiceContract? Does that mean for every minor change to my contracts I need a new assembly? How would I stop it from getting to literally hundreds in a couple of years time?
Some other solution?
Regardless of the solutions I think through, they all seem to have a major downside.
There doesn't seem to be (at least to me) of,
Preserving backwards compatibility until clients update
Keeping the clients trim with no bloat as the software evolves over time
Not significantly polluting my ServiceContract (overloads of the OperationContract need a new "name"). I already have things like the below, and it strikes me a nightmare to maintain over time.
Operation Contract complexity
[OperationContract]
public void DoSomethingWithMyContract(MyContract data);
[OperationContract(Name = "DoSomethingWithMyDataByAdditionalData"]
public void DoSomethingWithMyContract(MyContract data, MyContract2 additionalData);
I am looking for a solution that has worked over a period of time in a large scale environment. Blog entries and the like are very welcome.
Update 1
Looking through the limitations of using "schemaless" changes, different namespaces seems like the only sure method. However, its not quite working as expected, e.g. below
[ServiceContract(
Name = "IServiceContract",
Namespace = "http://myurl/2012/05")]
public interface IServiceContract1
{
// Some operations
}
[ServiceContract(
Name = "IServiceContract",
Namespace = "http://myurl/2012/06")]
public interface IServiceContract2
{
// Some different operations using new DataContracts
}
With the following service
public class MyService : IServiceContract1, IServiceContract2
{
// Implement both operations
}
and the following config
<service behaviorConfiguration="WcfServiceTests.ServiceBehavior"
name="Test.MyService">
<endpoint
address="2012/05"
binding="wsHttpBinding"
contract="Test.IServiceContract1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint
address="2012/06"
binding="wsHttpBinding"
contract="Test.IServiceContract2">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
Results in two contracts with two different names, I expected that I can point my clients to,
http://myurl.com/MyService.svc/2012/05 for the old version, and http://myurl.com/MyService.svc/2012/06
, but it seems like if I want to preserve the ServiceContract name they have to be two separate services rather than separate endpoint addresses for the same service?
Update 2
I ended up using the method I have described under update 1. Whilst the WSDL looks wrong, the service is indeed backwards compatible under older clients when I've tested this.

Both Microsoft and most of the respected WCF gurus out there will probably say the same thing: versioning should be handled using the contract namespaces.
I don't mean the .NET namespaces of your assemblies - I mean the actual WCF service (and data contract) namespaces - so you should have:
[ServiceContract(Namespace="http://services.yourcompany.com/Service1/V01"]
or something the like - some folks like to version by year/month:
[ServiceContract(Namespace="http://services.yourcompany.com/Service1/2012/05"]
This allows you to have multiple versions of the same service, and as long as clients come calling with an older version (indicated by the service namespace), they'll get the old version (as long as you still expose that).
See:
Best Practices: Data Contract Versioning
Service Versioning

Related

Configure WCF where ServiceContract and service implementation are in separate assemblies

I've looked at a lot of questions on this site that discuss, but don't directly answer this question. I have the following:
In Library.dll:
namespace LibraryNamespace
{
[ServiceContract]
public interface IService
{
[OperationContract]
void Operation();
}
}
In Implementation.dll:
namespace ImplementationNamespace
{
public class ServiceImplementation : IService
{
public void Operation()
{
// Do Something
}
}
}
In app.config:
<service name="ImplementationNamespace.ServiceImplementation">
<endpoint
address="ServiceImplementation"
binding="netTcpBinding"
contract="LibraryNamespace.IService" />
....
</service>
And I keep having a warning with contract="LibraryNamespace.IService". The program runs, but I have a feeling this warning is causing me more problems down the line.
The 'contract' attribute is invalid - The value
'LibraryNamespace.IService' is invalid according to its datatype
'serviceContractType' - The Enumeration constraint has failed.
It works when the ServiceContract and the service implementation are in the same assembly and namespace, but for some reason, it doesn't work here. How can I reference it properly?
I am not sure Why do you want to have the contract and implementation in separate dll? any specific reason? Generally they will be in same assembly and so in config file you can refer them with ease. One way to solve this is creating the service endpoint at runtime like below.
In your hosting project refer both the dll Library.dll and Implementation.dll and have the below code to add the endpoint
using LibraryNamespace;
using ImplementationNamespace;
// Specify a base address for the service
String baseAddress = "http://localhost/ServiceImplementation";
// Create the tcp binding
NetTcpBindings tcp = new NetTcpBindings();
// Define service and Create the endpoint
using(ServiceHost host = new ServiceHost(typeof(ServiceImplementation)))
{
host.AddServiceEndpoint(typeof(IService),tcp, baseAddress);
}

WCF Subscriber to Azure SB with multiple operations

I am trying to make a WCF Service that both publishes messages to a topic and also subscribes to that topic. The idea is to have my service expose endpoints for managing a customer (i.e. CreateCustomer, EditCustomer, DeleteCustomer, etc). Then I want it to publish a message to a topic after it completes each operation (i.e. OnCustomerCreated, OnCustomerChanged, OnCustomerDeleted, etc.)
For Example, A client application will hit the EditCustomer message on my service. I will immediately publish an OnCustomerChanged message with the customer object provided. My service (the same one the customer hit) will have another contract that takes an OnCustomerChanged and updates my database.
My question is, do I have to make a separate Subscription on my topic for each message type (i.e. OnCustomerChangedSubscription, OnCustomerDeletedSubscription, etc.) so that I can properly route messages of different types to the correct endpoint?
If that is case, I would need a bunch of single-method contracts so that I could configure the wcf endpoints properly:
i.e:
<service name="site.Services.Business.Managers.CustomerManager">
<!-- endpoint that clients will hit -->
<endpoint address="" binding="basicHttpBinding" contract="site.Services.Business.Contracts.ICustomerManager" />
<!-- endpoint that publishes messages-->
<endpoint address="sb://test-site.servicebus.windows.net/Managers/CustomerManager"
binding="netTcpRelayBinding"
contract="site.Services.Business.Contracts.ICustomerManager"
behaviorConfiguration="sbTokenProvider" />
<!-- One Endpoint for each message type (this will get very cumbersome and the contract will only have 1 method on it) -->
<endpoint address="sb://test-site.servicebus.windows.net/Managers/CustomerManager"
binding="netMessagingBinding"
listenUri="sb://test-site.servicebus.windows.net/Managers/CustomerManager/subscriptions/OnCustomerDeleted"
behaviorConfiguration ="sbTokenProvider"
contract="site.Services.Business.Contracts.CustomerManager.IOnCustomerDeleted" />
<endpoint address="sb://test-site.servicebus.windows.net/Managers/CustomerManager"
binding="netMessagingBinding"
listenUri="sb://test-site.servicebus.windows.net/Managers/CustomerManager/subscriptions/OnCustomerCreated"
behaviorConfiguration ="sbTokenProvider"
contract="site.Services.Business.Contracts.CustomerManager.IOnCustomerCreated" />
…etc
</service>
An alternative would be to create a single Subscriber (Allmessages), only having one contract with a HandleMessage(BrokeredMessage message) operation, and then determine inside that method with method to call on my service. That doesn't seem like I am doing the right thing there though either. I am essentially taking in all messages and determining the handler inside the service.
What I am looking for is a way to have a a service that implements 3 contracts, ICustomerPublisher (already have this), ICustomerManager (exposed over http to clients), and ICustomerSubscriber.
ICustomerSubscriber would look like:
[ServiceContract]
public interface ICustomerSubscriber
{
[OperationContract(IsOneWay = true)]
void OnCustomerCreated(ICustomerMessage message);
[OperationContract(IsOneWay = true)]
void OnCustomerDeleted(ICustomerMessage message);
[OperationContract(IsOneWay = true)]
void OnCustomerChanged(ICustomerMessage message);
}
and I would be able to call:
publisher.Publish<OnCustomerChanged>(new CustomerChangedMessage(customer));
and have my OnCustomerChanged method receive that message.
Any help would be appreciated.
First: Yes, if the service has per-request activation, then your SubscriptionClient won't get a chance to run except while the service responds to an external request, and it will have to be created and torn down every time. The only feasible way to keep the SubscriptionClient running would be to change activation to singleton.
But I think the better approach is to pull the SubscriptionClient out of this service entirely and have it run on its own. If you want it to run on-prem, then it could be in a Windows Service or console app; in the cloud, it could be a WebJob or Worker Role. Again, I don't see why your OnMessage method needs to be a WCF Operation.
Second: If there's only one Subscription, then each message can be received and completed by only one client. If multiple clients need to get a copy of each message, then each client needs its own subscription. The subscriptions can share the same filter conditions, or no conditions.
I was not able to find a suitable way to accomplish what I mentioned above. Instead, I did the following:
Created a default subscription to my customer topic with no filter.
In the constructor for my WCF service, I use the SubscriptionClient to register as a subscriber:
public CustomerManager()
{
//set up automapper and IoC
Initializer.Initialize();
Publisher = IoCContainer.GetContainer().Resolve<IPublisher>("CustomerManager");
Publisher.Subscribe("AllMessages");
var client =
SubscriptionClient.CreateFromConnectionString(CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString"), "customertopic", "AllMessages", ReceiveMode.PeekLock);
client.OnMessage(m =>
{
Console.WriteLine("Message Received.");
HandleMessage(m);
});
}
My HandleMessage method takes a BrokeredMessage as a parameter and then determines what internal operation to call based on the message body type.
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void HandleMessage(BrokeredMessage message)
{
var customerMessage = message.GetBody<CustomerMessage>();
switch (customerMessage.EventName)
{
case "OnCreated" :
OnCustomerCreated(customerMessage);
break;
case "OnDeleted" :
OnCustomerDeleted(customerMessage as OnDeleted);
break;
case "OnChanged" :
OnCustomerChanged(customerMessage as OnChanged);
break;
}
message.Complete(); //mark the message as completed
}
I have a couple of concerns though.
First, I use instance per request configuration for my service. Will this cause any kind of message consistency issues? Such as, when I have multiple instances of CustomerManager, will each one try and handle the same message, or will the SubscriptionClient ensure that only 1 CustomerManager will get the message?
Second, I want to be able to subscribe other services to my AllMessages subscription. One example is a notification service. I may want to be able to send a push notification to the account owner when a new customer is created (OnCustomerCreated), or I might want to ask the customer to verify the information that changed on their account (OnCustomerChanged). Can I still subscribe other services to the CustomerTopic AllMessages, or will marking the message complete (as I do at the end of my HandleMessage method) clear out the message for other subscribers also? More technically, will adding another subscriber to the AllMessages subscription result in multicasting or balancing?

RESTful web service auto-generate WADL

I have created a RESTful web service in C# and have deployed it to IIS. When I access the service HeadOffice.svc, I have the option to view the WSDL (HeadOffice.svc?wsdl). What I would like to do is have the option of viewing the WADL (e.g. HeadOffice.svc?wadl). Is this possible?
I have read around the place that the general opinion is that this is not the best practice. However, I need the WADL for a school assignment, so any help would be much appreciated.
Suppose you already know that WADL is not standard / not supported widely. And when somebody needs WADL, may be then better to use WS*/SOAP service + WSDL. So your task looks like very strange.
Anyway WADL is not supported "out of the box" in any REST implementation from Microsoft, neither WCF 3.5 Rest Starter Kit, neither WCF 4 REST, and ASP.NET WebAPI.
There are no reliable tools for WADL for .NET.
When your goal is to generate C# client code using WADL, believe me, you will spend more time as writing client code by yourself. And there are better solutions for that.
You can use new classes like HttpClient class or RestSharp or similar libraries to easily manually write your client and it will be even faster then googling for reliable WADL solution for .NET
Similar question on stackoverflow: Restful service in .NET with WADL instead of WSDL
UPDATE - Swagger:
For some years swagger has established itself as such format. You can either start writing service definition using swagger's YAML in the Swagger editor or let generate swagger from existing services, for .NET using Swashbuckle library. The second is something we had with WSDL, and swagger editor let's you generate client and server boilerplates. Regardless you are generating your server or client or not fan of it, swagger is actually a very good contract exchange format for REST service, not ideal but good option.
Why Swagger4Wcf
•Manually writing yaml description for swagger and maintain it especially WCF services are boring.
•There is a nuget package called Swagger4WCF that automatically generates yaml description for swagger 2.0 for each interface matching attributes used by WCF (ServiceContract/OperationContract/WebGet/WebInvoke).
2. How Swagger Works in the Background
Swagger4WCF uses NuPack post build pattern to trigger at build time.
https://www.codeproject.com/Tips/1190360/How-to-setup-a-managed-postbuild-without-scripting
At build time, it will detect assemblies present in output directory, open them with mono.cecil (to reflect assemblies) to generate expected yaml description for swagger 2.0.
Swagger4WCF detects WebGet/WebInvoke to provide Verb/Method in serialization style in yaml.
Steps to implement Swagger in your application:
Install SwaggerWcf package
Configure WCF routes
We have to add the route in the Application_Start method inside Global.asax
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("v1/rest", new WebServiceHostFactory(), typeof(BookStore)));
RouteTable.Routes.Add(new ServiceRoute("api-docs", new WebServiceHostFactory(), typeof(SwaggerWcfEndpoint)));
}
Note: Edit Web.config and add the following (if it doesn't exist yet) inside the system.serviceModel block
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
Configure WCF response auto types (optional)
We have to add the following to Web.config. This will allow the WCF service to accept requests and send replies based on the Content-Type headers.
<behavior name="webHttpBehavior">
<webHttp defaultOutgoingResponseFormat="Json" automaticFormatSelectionEnabled="true"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
Decorate WCF services interfaces
For each method, we have to configure the WebInvoke or WebGet attribute, and add a SwaggerWcfPath attribute.
[SwaggerWcfPath("Get book", "Retrieve a book from the store using its id")]
[WebGet(UriTemplate = "/books/{id}", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
Book ReadBook(string id);
Decorate WCF services class
• Add the SwaggerWcf and AspNetCompatibilityRequirements attributes to the class providing the base path for the service.
• For each method, add the SwaggerWcfTag to categorize the method and theSwaggerWcfResponse for each possible response from the service.
[SwaggerWcfTag("Books")]
[SwaggerWcfResponse(HttpStatusCode.OK, "Book found, value in the response body")]
[SwaggerWcfResponse(HttpStatusCode.NoContent, "No books", true)]
public Book[] ReadBooks()
{
}
Decorate data types used in WCF services
[DataContract]
[Description("Book with title, first publish date, author and language")]
[SwaggerWcfDefinition(ExternalDocsUrl = "http://en.wikipedia.org/wiki/Book", ExternalDocsDescription = "Description of a book")]
public class Book
{
[DataMember]
[Description("Book ID")]
public string Id { get; set; }
[DataMember]
[Description("Book Title")]
public string Title { get; set; }
[DataMember]
[Description("Book First Publish Date")]
public int FirstPublished { get; set; }
[DataMember]
[Description("Book Author")]
public Author Author { get; set; }
[DataMember]
[Description("Book Language")]
public Language Language { get; set; }
}
Reference:- https://github.com/abelsilva/swaggerwcf
That's it wcf for Swagger implemented.
Please free if you face any issue.
Thanks,
Abhi

I need to use 2 different SoapServices but I can only access 1 at the time, why?

I have a school assignment and I've run into a problem which I just can't understand what's wrong.
In my school assignment we created a Service which is identical to my teachers service. The point of the service were to be able to communicate with our chat clients which we connected to our service.
The problem I have is when I got the task to be able to switch between the two services (which is the type servicename.ServiceSoapClient("ServiceSoap12")). In my service, which I created I put in a namespace to my teachers service: [WebService(Namespace = "http://dsweb.tmd.hv.se/users/wsi400/ChatService/")]
(That was for a later purpose, see below)
The code for my service (which should be almost identical (same return and input values)) is here: http://pastie.org/2461928
Now to the real problem..
When creating the client for one service is a piece of cake, trying it to be able to change between them using only 1 reference in the client seems impossible (but others have managed to do it, but after examination of code and such, we have no idea what's wrong with mine). I have, as I've said added the local reference to my service (my asmx file) and that's because I apparently needed the namespace pointed to my teachers service from mine.
When connecting to my service I use the following code:
wsChatService.ServiceSoapClient wsService = new wsChatService.ServiceSoapClient("ServiceSoap12");
When adding my service, it generates a lot of stuff in app.config and I changed a value to be able to switch to my teachers service:
<client>
<endpoint address="http://dsweb.tmd.hv.se/users/wsi400/ChatService/Service.asmx" binding="basicHttpBinding"
bindingConfiguration="ServiceSoap" contract="wsChatService.ServiceSoap"
name="ServiceSoap" />
<endpoint address="http://dsweb.tmd.hv.se/users/wsi400/ChatService/Service.asmx" binding="customBinding"
bindingConfiguration="ServiceSoap12" contract="wsChatService.ServiceSoap"
name="ServiceSoap12" />
</client>
Now I have tried to switch with a simple button and the test function always works when switching between the services but depending on what service I choose to use as an assembly reference, that's the one that I can post messages to.
This is the code for the client:
private void service1_Click(object sender, EventArgs e)
{
if (connNr == 2)
{
wsService = new wsChatService.ServiceSoapClient("ServiceSoap12", "http://localhost:63280/Service.asmx");
connNr = 1;
MessageBox.Show("Connection changed to: Markus \nTesting connection: " + wsService.Test());
textarray.Text = "";
MessageBox.Show("Trying to send message: " + wsService.SendMessage("babbel", "Connecting..", "Connected?"));
}
}
private void service2_Click(object sender, EventArgs e)
{
if (connNr == 1)
{
wsService = new wsChatService.ServiceSoapClient("ServiceSoap12", "http://dsweb.tmd.hv.se/users/wsi400/ChatService/Service.asmx");
connNr = 2;
MessageBox.Show("Connection changed to: http://dsweb.tmd.hv.se/users/wsi400/ChatService/Service.asmx \nTesting connection: " + wsService.Test());
textarray.Text = "";
MessageBox.Show("Trying to send message: " + wsService.SendMessage("babbel", "Connecting..", "Connected?"));
}
}
I used to run into this all the time
This issue is usually because of the namespace used in the WSDL definition. for example I used to have issues with .NET clients of my PHP SOAP services on different servers.
I used namespaces such as dev.myserver.co.uk, test.myserver.co.uk and srv1.myserver.co.uk respectively on my development, test and live servers. When I did this my .Net clients had to be rebuilt each time, like the issue you are experiencing.
I changed my namespace to a fictional one (namespaces don't have to actually exist) xml.myserver.co.uk on each of my web services and then you can re-use the generated proxy classes in your C# client apps.
The problem is that if you don't control the definition for the WSDL then you can't easily change it.
One hacky way around it is to save the WSDL definition locally, make your changes and have your client point to that instead. That way you can re-use the proxy class but invoke the methods against different servers.

How to create API in C# to push or receive data?

Hi I would like to create an API for my website to send and receive data.
For example I need my customers to upload products, single or multiple items. Product feeds can be send daily, weekly or monthly.
Product Name:
Product Color:
Product Weight:
Product Images:
Also I need functionality to send this data to another server. And it should be user friendly.
But I don't have any idea where to start, what technology to use to make it simple and sufficient.
I have background in Asp.Net, C#. It would be great to see an example how to approach it.
Its better you go for the WEB SERVICES (WCF SERVICE) to achieve this easily.
REST via WCF would be the best option. Here is a good article series introducing you to REST with WCF: REST in WCF
There are two distinct pieces of functionality here, and keep in mind that they should essentially be kept separate. Each of them is defined by "who is integrating to whom."
In the first piece, you want to expose a web service API to which clients can connect and send/receive data (the latter of which is on request only). How you want to define this web depends on how you want to expose it to clients, how they want to connect, etc. Common options are:
SOAP Web Service (classic ASP .NET web service)
WCF Service (think of it as a more modern ASP .NET web service)
You can even expose a manual service by defining your own WSDL for clients to consume, or a service that accepts and returns JSON to be more JavaScript-friendly for clients, etc. There are many options. But the above two are your most common choices.
The second piece is where you want to "push" data to another service. This is something that the other service needs to expose and you need to integrate to that. So the design should begin on that side. If you're in charge of that design, just approach it the same way as above. Expose a service there and then, using the same technologies that expose the services, consume them in your application.
The main thing to keep in mind here is to keep the two separate, because trying to expose a web service which at the same time consumes another web service will likely lead to confusion and some non-obvious work-arounds. These are separate concerns and need to keep separated on a logical level, even if the end user doesn't know how separated they are.
Here is a bare minimum WCF Service which returns a product in JSON. To try it out, create a .NET 4.0 Full Profile console application. Run the program, and put this in your browser's address bar: http://localhost:8080/productservice/Product/23
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WCFServiceExample
{
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
}
[ServiceContract(Namespace = "")]
public interface IProductService
{
[WebGet(UriTemplate = "Product/{id}", ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
Product Product(string id);
}
public class ProductService : IProductService
{
public Product Product(string id)
{
return new Product { Id = id, Name = "A Sample Product" };
}
}
class Program
{
private static ServiceHost servHost;
static void Main(string[] args)
{
StartService();
Console.WriteLine("\n\nPress any key to exit...");
Console.ReadKey();
}
public static void StartService()
{
servHost = new ServiceHost(typeof(ProductService));
servHost.Open();
}
~Program()
{
if (servHost != null)
{
servHost.Close();
}
}
}
}
App.config
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logKnownPii="true" logMalformedMessages="true"
logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
<endToEndTracing propagateActivity="true" activityTracing="true"
messageFlowTracing="true" />
</diagnostics>
<services>
<service name="WCFServiceExample.ProductService">
<endpoint
address="http://localhost:8080/productservice"
contract="WCFServiceExample.IProductService"
kind="webHttpEndpoint" />
</service>
</services>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

Categories