cheap oakleys replica michael kors bags cheap christian louboutin online elite jerseys wholesale cheap nfl jerseys discount ray bans cheap michael kors cheap ray bans replica oakleys wholesale replica michael kors wholesale oakley sunglasses cheap fake ray bans cheap jerseys china cheap christian louboutin outlet fake cheap oakleys cheap oakleys cheap jerseys sale cheap christian louboutin discount oakleys wholesale nfl jerseys cheap michael kors handbags michael kors handbags discount christian louboutin cheap jerseys michael kors on sale discount ray bans wholesale jerseys cheap michael kors fake oakleys online cheap michael kors bags replica ray bans discount ray bans authentic jerseys cheap christian louboutin cheap oakleys cheap oakleys outlet nfl jerseys red bottoms shoes on sale cheap ray bans cheap nfl jerseys cheap replica oakleys michael kors on sale cheap christian louboutin outlet Cheap Elite Jerseys cheap michael kors cheap ray bans cheap jerseys free shopping cheap fake oakleys cheap oakleys sale cheap michael kors outlet ray bans shop fake cheap oakleys cheap authentic nike jerseys christian louboutin online fake cheap oakleys fake oakleys store cheap jerseys wholesale cheap christian louboutin replica oakleys cheap jerseys wholesale cheap replica oakleys michael kors handbags wholesale jerseys china discount nhl jerseys wholesale replica michael kors cheap ray bans cheap jerseys cheap fake oakleys fake oakleys cheap michael kors store cheap ray bans wholesale oakleys jerseys wholesale christian louboutin outlet cheap mlb jerseys oakley sunglasses authentic jerseys christian louboutin outlet cheap replica oakleys wholesale authentic jerseys wholesale mlb jerseys michael kors handbags cheap jerseys online shopping cheap nhl jerseys michael kors bags cheap fake oakleys cheap jerseys from china cheap fake oakleys 2016 cheap fake oakleys cheap michael kors cheap discount ray bans fake cheap oakleys cheap jerseys free shopping cheap christian louboutin online wholesale nfl jerseys cheap jerseys from china wholesale christian louboutin wholesale mlb jerseys official jerseys fake cheap oakleys cheap michael kors handbags wholesale jerseys cheap wholesale jerseys cheap fake oakleys oakley sunglasses cheap discount oakleys oakleys sunglasses usa cheap michael kors online wholesale and retail oakleys cheap michael kors outlet cheap wholesale jerseys wholesale cheap jerseys china cheap replica oakleys fake oakleys online authentic jerseys wholesale ray bans fake cheap oakleys jerseys wholesale replica ray bans wholesale sunglasses wholesale mlb jerseys cheap cheap nfl jerseys cheap michael kors outlet cheap fake ray bans cheap oakleys sale cheap fake ray bans oakleys sunglasses michael kors bags fake cheap oakleys fake cheap oakleys authentic wholesale jerseys nhl jerseys cheap michael kors outlet cheap oakleys online wholesale jerseys fake ray bans online store michael kors handbags outlet wholesale jerseys china fake ray bans ray bans outlet cheap christian louboutin cheap nba jerseys cheap ray bans cheap ray bans wholesale nfl jerseys wholesale sunglasses michael kors bags outlet cheap ray bans on sale fake cheap oakleys cheap nfl jerseys cheap nhl jerseys cheap oakleys cheap jerseys cheap fake oakleys michael kors outlet cheap jerseys store fake ray bans christian louboutin shoes discount nba jerseys michael kors for sale cheap fake oakleys fake ray bans sunglasses cheap michael kors handbags oakley sunglasses michael kors handbags michael kors on sale fake cheap oakleys cheap nfl jerseys replica oakleys cheap oakleys outlet cheap oakleys cheap authentic nfl jerseys paypal cheap fake oakley sunglasses cheap oakleys cheap jerseys paypal
Inder Singh's Blog
Mar 162016
 

I have an email account hosted with Arvixe and I suddenly started receiving hundreds of Spam emails everyday. I found a blog post on Arvixe that MxGuardDog is a free anti spam software solution for stopping Spam email, I tried it out and it does work. I had to be patient though it takes a few days for the Spam emails to be blocked, a couple still come through but still its a pretty good solution.

 Posted by on March 16, 2016
Apr 072013
 

I always heard the terms like loosely-coupled systems, mock objects, database independent unit tests, etc. which sounded nice but they were all abstract concepts for a long time. It was after a many years of work experience that I really grasped them for implementation purpose and realized more meaning than some abstract concepts. In this post I will share my experiences in using all these concepts and write some tests for business logic. The term Unit Testis being loosely used here because these tests might not be unit tests in true sense; they are just automated tests to verify business logic. The concepts explained here might not be anything new but the idea here is to enhance understanding by providing some simple examples. Please note that the example used here is very simple but the same principles can be applied to much more complex scenarios to yield quality code.

The main pre-requisite for unit tests is that there should be some real business logic to test, if your application is basic data entry which writes out the object constructed from form data to database then there is not a whole lot that can be done to make tests database independent. Now, assuming you have some real business logic to test the business classes need to be designed in a certain way to be able to perform some database independent testing.

Let’s start with some ground rules and then we can elaborate using concrete examples:

  • Domain objects which represent business entities are persistence ignorant
  • Repositories used for a persistence related activities
  • Command classes implemented to perform business transaction on business entities

We will design classes for an Order Processing system, assumption is that the Order is already saved to the database (user submitted the order using a web application) and backend job processes these pending orders.
The task at hand is to process the Order and following are the requirements:

  • Order must be in status New or Pending
  • Check Item Inventory to see if Order can be fulfilled
    • If all order items are available then Dispatch Order Message to Warehouse System and update Order Status to Complete
    • Else update Order Status to Pending
  •   public class Order
        {
            public int OrderId { get; set; }
            public DateTime OrderDate { get; set; }
            public List<OrderDetail> OrderDetails { get; set; }
            public string OrderStatus { get; set; }
            public int? OrderDispatchConfirmationNumber { get; set;}
    
            public string ShippingAddress { get; set; }
        }
    
        public class OrderDetail
        {
            public int OrderDetailId { get; set; }
            public int ItemId { get; set; }
            public decimal ItemPrice { get; set; }
            public int Quantity { get; set; }
        }
    
        public class ItemInventory
        {
            public int ItemId { get; set; }
            public int QuantityAvailable { get; set; }
        }
    
    
    
    public interface IOrderRepository
        {
            Order GetByOrderId(int orderId);
            void SaveOrder(Order order);
        }   
    
    
    public interface IWarehouseSystem
        {
            public ItemInventory GetItemInventoryByItemId(int itemId);        
            public int DispatchOrder(Order order);
        }
    
    

    The key to writing database independent tests is to encapsulate the business transaction code like Processing Order into an object. Instead of mixing the business transaction code with the business entity create a class whose sole purpose is to perform the business transaction. In our example, instead of implementing ProcessOrder function in Order class implement a separate class ProcessOrderCommand.

    ProcessOrderComand Data Requirements:

    1. Read Order information
    2. Validate Order is in status New or Pending
    3. Read Item Inventory information
    4. If all the items on the Order are available then
      • Dispatch Order to Warehouse System
      • Update Order to Complete
    5. Else Update Order status to Pending and no further processing needed

    ProcessOrderCommand is implemented to use interfaces for external dependencies (data repository and warehouse system), the result is a loosely couple system where fake implementations can be injected to achieve our goal of database independent tests. Now, let’s implement this class.

    
      public class ProcessOrderCommand
        {
            public IOrderRepository OrderRepository { get; set; } /* External Dependency */
            public IWarehouseSystem WarehouseSystem { get; set; } /* External Dependency */
    
            public int OrderId { get; set; } /* Input Data */
    
            public void ExecuteCommand()
            {
                Order order = this.OrderRepository.GetByOrderId(this.OrderId);
    
                if (order == null)
                    throw new InvalidOperationException("Order not found for OrderId - " + this.OrderId);
    
                if (order.OrderStatus != "Pending" && order.OrderStatus != "New")
                    throw new InvalidOperationException("Order must be in status Pending or New to be processed");
    
                bool orderItemsAvailable = CheckOrderItemAvailability(order);
    
                if (orderItemsAvailable)
                {
                    order.OrderDispatchConfirmationNumber = this.WarehouseSystem.DispatchOrder(order);
                    order.OrderStatus = "Shipped";
                }
                else
                {
                    order.OrderStatus = "Pending";
                }
    
                this.OrderRepository.SaveOrder(order);
            }
    
            private bool CheckOrderItemAvailability(Order order)
            {
    
                foreach (OrderDetail orderDetail in order.OrderDetails)
                {
                    ItemInventory itemInventory = this.WarehouseSystem.GetItemInventoryByItemId(orderDetail.ItemId);
                    if (itemInventory == null || itemInventory.QuantityAvailable < orderDetail.Quantity)
                        return false;
                }
    
                return true;
            }
        }
    

    ProcessOrderCommand relies on interfaces so we can setup a mock OrderRepository to return an Order object in status Complete and then try to execute the command. The expected result is an exception and a unit test can be written to verify this validation rule. Since, we can use a mock implementation of IOrderRepository to return an Order in status Complete there is no need to create Order records in database to be able to test such logic. Hence, we have achieved our goal of writing database independent unit tests!

    Following are examples for Mock implementations:

    
      public class MockOrderRepository : IOrderRepository
        {
            public Order GetByOrderId(int orderId)
            {
                Order order = null;
    
                if (orderId == 1) ///New Order
                {
                    order = new Order { OrderId = 1, OrderDate = DateTime.Now, OrderStatus = "New", ShippingAddress = "45 University Ave, Minneapolis MN 55890" };
                    order.OrderDetails = new List<OrderDetail>();
                    order.OrderDetails.Add(new OrderDetail() { OrderDetailId = 100, ItemId = 1, ItemPrice = 50, Quantity = 10 });
                }
                else if (orderId == 2)
                {
                    order = new Order { OrderId = 2, OrderDate = DateTime.Now, OrderStatus = "Pending", ShippingAddress = "45 University Ave, Minneapolis MN 55890" };
                    order.OrderDetails = new List<OrderDetail>();
                    order.OrderDetails.Add(new OrderDetail() { OrderDetailId = 110, ItemId = 2, ItemPrice = 10, Quantity = 50 });
                }
                else if (orderId == 3) //Complete Order
                {
                    order = new Order { OrderId = 3, OrderDate = DateTime.Now, OrderStatus = "Complete", ShippingAddress = "45 University Ave, Minneapolis MN 55890" };
                    order.OrderDetails = new List<OrderDetail>();
                    order.OrderDetails.Add(new OrderDetail() { OrderDetailId = 200, ItemId = 6, ItemPrice = 50, Quantity = 10 });
                }            
    
    
                return order;
            }
    
            public void SaveOrder(Order order)
            {
              //Does Nothing - Simulate Order saved successfully
            }
        }
    
        public class MockWarehouseSystem : IWarehouseSystem
        {
    
            public ItemInventory GetItemInventoryByItemId(int itemId)
            {
                if (itemId == 1)
                    return new ItemInventory() { ItemId = 1, QuantityAvailable = 500 };
                else if (itemId == 3)
                    return new ItemInventory() { ItemId = 3, QuantityAvailable = 10 };
                else if (itemId == 6)
                    return new ItemInventory() { ItemId = 6, QuantityAvailable = 100 };
                else
                    return null;
                    
            }
    
            public int DispatchOrder(Order order)
            {
                //Does Nothing - Simulates successful Order Dispatch
                return (new Random()).Next();
            }
        }
    
    

    It might be quite a bit of coding effort to write the mock implementation and that’s where Mocking frameworks come into play. In another post, I will describe how to use a Mocking Framework (Moq) to setup mock implementations of IOrderRepository and IWarehouseRepository. Using the mocking framework we will be able to write even more extensive tests but for now the following would suffice.

    
    [TestMethod]
           public void InvalidOrderIdTest()
           {
               int invalidOrderId = 10;
    
               ProcessOrderCommand processOrderCommand = new ProcessOrderCommand();
               processOrderCommand.OrderRepository = new MockOrderRepository();
               processOrderCommand.WarehouseSystem = new MockWarehouseSystem();
               processOrderCommand.OrderId = invalidOrderId;
    
               try
               {
                   processOrderCommand.ExecuteCommand();
                   Assert.Fail("ProcessOrderCommand expected to throw an exception for invalid OrderId");
               }
               catch (Exception ex)
               {
                   Assert.IsTrue(ex.Message == "Order not found for OrderId - " + invalidOrderId, "Expected Exception Message not found for Invalid OrderId");
               }
           }
    
            [TestMethod]
            public void InvalidOrderStatusTest()
            {
                int completeOrderid = 3;
    
                ProcessOrderCommand processOrderCommand = new ProcessOrderCommand();
                processOrderCommand.OrderRepository = new MockOrderRepository();
                processOrderCommand.WarehouseSystem = new MockWarehouseSystem();
                processOrderCommand.OrderId = completeOrderid;
    
                try
                {
                    processOrderCommand.ExecuteCommand();
    
                    Assert.Fail("ProcessOrderCommand expected to throw an exception for invalid OrderId");
                }
                catch (Exception ex)
                {
                    Assert.IsTrue(ex.Message == "Order must be in status Pending or New to be processed", "Expected Exception Message not found for Complete Order");
                }
            }
    

    Note: Performing string comparison in the unit tests might not be a good idea, I did not want to add more code to this post that’s why I have resorted to string comparison but in real world applications you might want to define an enumeration with all possible error conditions and throw a custom exception which has a property of error condition enumeration type. Then your tests can compare against the Enumeration.

Mar 172013
 

I will be writing more introductory posts on my experience in using Castle Windsor Inversion of Control Container and Dependency Injection concepts later but this post is a solution to one of the problems I encountered which required custom lifestyle for Castle Windsor. Inversion of Control and Castle Windsor principles are pre-requisites to be able to follow this blog post, so read on if you are familiar with above mentioned concepts and are stuck with a similar problem in your implementation….

The application is a WCF Service web application where Castle Windsor Container injects dependencies into WCF service classes, to be more specific dependencies here are Repository classes which use NHibernate to access data from database. The repositories make use of NHibernate ISession which also gets injected by Castle Windsor. The application initially only consisted of services using data access code and the NHibernate Session was configured to use PerWcfOperation lifestyle so that only one NHibernate Session object is instantiated for a service method call. Hence, if service method makes use of multiple repositories then all of the repositories share the same NHibernate Session object injected by DI Container. I will refer to PerWcfOperation lifestyle as out of the box lifestyle, although it is not part of standard Castle Windsor but available as part of WCF Integration Facility. The application evolved and there was a need for a web page as well as an Http Handler to access data but the WcfPerOperation lifestyle is not available within the context of web request and hence any attempt to resolve the NHibernate Session failed. The out of the box lifestyles are set at compile time so either I could make the data access code work within the Web by changing the lifestyle to PerWebRequest or within the Wcf service methods by setting the lifestyle to PerWcfOperation but not both at the same time. Hence, there was a need for a hybrid lifestyle for the NHibernate Session dependency object where the lifestyle is determined at runtime based on whether the data access code is being executed within a Web Request or WcfOperation context.

I wanted a very simple solution which solves the problem without any bells and whistles. I did find some code on web which addressed the issue but it was little bit more complicated and the module never made it past the alpha version.

The basic understanding of inner workings of out of the box lifestyles in Castle Windsor (or its facilities) provides an insight into achieving the desired hybrid lifestyle. DI container manages the lifespan of registered components, if the component does not have a transient lifestyle the instance needs to be stored in some kind of cache for future resolve requests for that component. So, let’s look into the following out of the box lifestyles
• PerWebRequest – DI Container stores components of this lifestyle in HttpContext which is available only within the context of a web request.
• PerWcfOperation – Components of this lifestyle are stores in Wcf OperationContext which is available only within the context of a Wcf operation

An attempt to resolve an object of lifestyle PerWebRequest fails outside a web request and similarly an attempt to resolve an object of lifestyle PerWcfOperation fails outside Wcf operation. Now our solution for hybrid lifestyle relies on these out of the box lifestyles and requires only a handful of classes. It determines the lifestyle of the component dynamically at runtimes based on the following conditional logic in order:
• Set Lifestyle to PerWcfOperation if OperationContext is available
• Set Lifestyle to PerWebRequest if HttpContext is available
• Set Lifestyle to Transient which does not store the resolved component and creates a new component on each resolve request.

The above mentioned logic is wired into the Castle Windsor by implementing following two classes:
• HybridLifestyleScopAccessor – An implementation of Castle.MicroKernel.Lifestyle.Scoped. IScopeAccessor and contains the code for above mentioned conditional logic.
• TransientScopAccessor – This again is an implementation of Castle.MicroKernel.Lifestyle.Scoped.IScopeAccessor which will be used if neither HttpContext nor OperationContext are available.

There is no need to implement accessors for PerWcfOperation and PerWebRequest because they are already available out of the box.

/// <summary>     
/// Custom LifeStyle to automatically detect the context in which the application is being used and return appropriate scope for the objects. Following is the order in which scopes are detected and the first one found is returned:     
/// - WCF Operation     
/// - Web Request     
/// - Transient
/// </summary>
/// <remarks>        
/// <para>     
/// No new scope is implemented, it just  provides a Hybrid model for scopes provided by Castle Windsor and WCF Integration Factility.     
/// </para>     
/// <para>      
/// Primarily introduced so that the Data Access code using NHibernate Sessions can work within WCF Operation as well as Web Request.     
/// </para>     
/// <para>     
/// Following configuration must be added to web.config for the WebRequest Lifetime Scope to work:     
/// <configuration>     
///     <system.webServer>     
///         <modules>     
///             <add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />     
///         </modules>     
///     </system.webServer>     
/// </configuration>     
/// </para>     
/// </remarks> 
public class HybridLifeStyleScopeAccessor : IScopeAccessor
{
   private readonly IScopeAccessor _WcfOperationScopeAccessor = new Castle.Facilities.WcfIntegration.Lifestyles.WcfOperationScopeAccessor();
   private readonly IScopeAccessor _WebRequestScopeAccessor = new Castle.MicroKernel.Lifestyle.WebRequestScopeAccessor();
   private readonly IScopeAccessor _TransientScopeAccessor = new TransientScopeAccessor();

  ///<summary> 
  /// If Wcf Opertaion Context is available then returns WcfOperation Lifetime Scope
  /// Else If HttpContext is avilable then return WebRequest Lifetime Scope
  /// Else Returns Transient LifetimeScope
  /// </summary>
  public ILifetimeScope GetScope(Castle.MicroKernel.Context.CreationContext context)
  {
     if (OperationContext.Current != null)
       return this._WcfOperationScopeAccessor.GetScope(context);
     else if (HttpContext.Current != null)
       return this._WebRequestScopeAccessor.GetScope(context);
     else
       return this._TransientScopeAccessor.GetScope(context);
  }

#region IDisposable
   private bool disposed = false;

   protected virtual void Dispose(bool disposing)
    {
      if (!disposed)
       {
          if (disposing)
           {
              this._TransientScopeAccessor.Dispose();
              this._WcfOperationScopeAccessor.Dispose();
              this._WebRequestScopeAccessor.Dispose();
           }
           disposed = true;
        }
    }

  public void Dispose()
   {
       Dispose(true);
       GC.SuppressFinalize(this);
   }
#endregion
}

TransientScopeAccessor is a custom accessor which also needs to be implemented

/// <summary>
/// Used by the HybridLifeStyleScopeAccessor class to provide the Transient LifeStyle as fallback
/// </summary>
public class TransientScopeAccessor : IScopeAccessor
{
  public ILifetimeScope GetScope(Castle.MicroKernel.Context.CreationContext context)
   {
       return new DefaultLifetimeScope();
   }

 #region IDisposable

 private bool disposed = false;

 protected virtual void Dispose(bool disposing)
 {
   if (!disposed)
    {
       disposed = true;
    }
  }

 public void Dispose()
 {
    Dispose(true);
    GC.SuppressFinalize(this);
  }
  #endregion
 }

A component can be registered with this Hybrid Lifestyle using the following line of code:

container.Register(Component.For().LifestyleScoped())
Nov 272012
 

Background
When WCF services get consumed by .NET clients, framework takes care of what gets written onto the wire and all the complexity related to SOAP message serialization, security, etc. is hidden behind the scenes. One does not need to pay much attention to the underlying details. My current project gave me this fabulous opportunity to look under the hood because the WCF services are consumed by external business partner who will be implementing the client in Java. The business partner team has not involved the developers in the project yet, the business analyst is using the soapUI tool to test drive the services and was unable to connect to the service because of some authentication issues. Hence, I got assigned the task of investigating the problem. In this post, I will walk through some of the quirks in the soapUI tool and show how to make it work but first I will start with a little background of the different components/concepts.

Basic Authentication
The services are secured using Basic Authentication protocol over SSL which is pretty standard. In simple terms, the username/password credentials are from Windows Active Directory domain and need to be sent in the HTTP header.

soapUI Tool
soapUI is an open-source tool which can be used to test the SOAP based services. You can read more about it as well as download a free copy from the their website.

The problem was discovered in soapUI 4.5.0, it might exist in other versions of the tool as well but I have not verified yet.

Problem and the Solution
When a service method request is sent to the service the username and password credentials need to be sent in the HTTP header as part of the request. By default this does not happen and the following is the workaround on how to achieve this to make a successful call to WCF Service secured with Basic Authentication.

If you are new to using soapUI, it’s a pretty straight-forward and simple to use tool. You will need to create a new soapUI project using the WSDL for the service.
Following are two simple setting changes you need to make so that Username\Password credentials are sent as part of the request:
1. Open Preferences dialog for the tool using File > Preferences menu and check the “Authenticate Preemptively” checkbox on the “Http Settings” tab as shown on the screenshot below.

soapUI Preferences Screenshot

soapUI (File > Preferences)

2. Specify username and password strictly as shown in the screenshot below. Username property must be set to username along with the domain name, e.g. Domain\Username and Password for the Password Property. Specifying domain name in the Domain property did not work, also specifying username without domain name did not yield the correct results.

soapUI (Request Username and Password Properties)

soapUI (Request Username and Password Properties)

Note: Service name, services methods and usernames are hidden in the screenshots for client privacy reasons.
For those curious how I figured this out. I used Fiddler to see the exact messages sent for successful calls made by .NET Client and then compared that message to the one sent by soapUI. I found that an extra piece of information was included for the successful and then trial/error led me to the successful call.

Mostly I use WCF Test Client provided with .NET Framework for quick testing on the services but it does not allow making calls to WCF Services secured using Basic Authentication (or at least I haven’t figured out a way yet) so soapUI can be handy to .NET Developers who are not planning to consumer the services from JAVA or some other language.

 Posted by on November 27, 2012
Mar 102009
 

I needed to expose a few WCF services to be consumed by Adobe LiveCycle server and ran into certain interoperability issues. With the help of some very useful blog posts and sample code (provided along with the blog posts) I was able to get past the hurdle. In this post I have compiled the complete details of the problem, solution and the references used.

The root of the problem was WSDL generated by WCF, by default the WSDL generated for a WCF service can consist of multiple files. In certain situations the main WSDL file can include a reference to another WSDL file which in turn refers to separate XSD files to describe the data types used in ServiceContracts. When client consuming the service is developed using .NET then .NET tools are able to process such WSDL (spanning multiple files) without any problem, it might not be a problem for client developed using some other technologies either but in our case the Adobe LiveCycle server was not able to process such WSDL correctly. So, the solution was to flatten the WSDL into one long document containing everything.

Problem Definition

Now, I will explain the problem we are trying to solve using some code. The sample I am using is again from Learning WCF by Michele Bustamante.

One of the DataContracts:

[DataContract(Namespace="http://schemas.thatindigogirl.com/samples/2006/06")]
public class PhotoLink: LinkItem
{
   public PhotoLink()
   {
     this.LinkItemType= LinkItemTypes.Image;
   }
}

ServiceContract:

[ServiceContract(Name="PhotoUploadContract",Namespace="http://www.thatindigogirl.com/samples/2006/06")
public interface IPhotoUpload
{
  [OperationContract]
  void UploadPhoto(PhotoLink fileInfo, byte[] fileData);
}

The WSDL generated for the above Service without any customization consists of a total of five files – two WSDL files and three XSD files. Instead of showing the complete text of the WSDL files I will just show the relevant parts.

The first WSDL file generated from MEX endpoint is relatively short and contains the following import statement:


The location attribute points to the second WSDL file and this second WSDL file further refers to external XSD files.The schemaLocation attributes provide the location of external XSD files.

Solution Step 1

I used quite a few blog posts but the following article by Christian Weyer was most helpful, you can also download code for free which will flatten out the generated WSDL.

Link to the post: Improving WCF Interoperability: Flattening your WSDL

Christian Weyer showed multiple solutions to the tackle the problem:

  • A custom endpoint behavior.
  • A custom ServiceHost.
  • A custom ServiceHostFactory to be used when service is hosted in IIS (this was my case).

I used the custom ServiceHostFactory to host the service and was able to solve the problem partially, this time WSDL generated consisted of only two files. The first WSDL file referenced the second WSDL file and all the XSD schema definitions were included in line in the second WSDL file. This is one step forward but still it did not solve our problem completely because Adobe LiveCycle required all the content to be in one WSDL file.

The first WSDL file stays the same as before and refers to the second WSDL file, but the second WSDL file contains all XSD schemas inline.

Solution Step 2

Two more changes were required to get all the WSDL generated in one file:
1. Service Endpoint needs to be in the same namespace as the ServiceContract.

2. A ServiceBehavior needs be to the service implementation type with the same namespace as ServiceContract. Example, Service implementation was modified to include a ServiceBehavior attribute as follows:

[System.ServiceModel.ServiceBehavior(Namespace = "http://www.thatindigogirl.com/samples/2006/06")]
public class PhotoManagerService: IPhotoUpload
{
   public void UploadPhoto( ContentTypes.PhotoLink fileInfo, byte[] fileData)
   {
      PhotoUploadUtil PhotoUploadUtil = new PhotoUploadUtil();
      photoUploadUtil.SavePhoto(fileInfo, fileData);
   }
}

With the above two changes in place along with custom ServiceHost, desired results were achieved and the entire WSDL generated including XSD schemas was in one long file.

Please Note: There was no need to change namespace of the DataContract or the Mex Endpoint.

Conclusion

I was not too happy to discover this issue, wish there was simpler configuration based solution to generate WSDL in one document but the good thing is that WCF is extensible enough that if we dig beneath the surface desired solutions can be developed. Hence, I won’t jump on the bandwagon that WCF is not ready for interoperability.

 Posted by on March 10, 2009