Category Archives: .NET

WCF Callback function – FileSystemWatcher

FileSystemWatcher class allows to get notification on any change in the directory. The notification can be even filtered by changes like rename, delete and all. File types can be specified to the class to allow notification for a particular file types.

Code Snippet
  1. Dim watchFile As New FileSystemWatcher()
  2.         watchFile.Filter = ConfigurationManager.AppSettings.Item(“FileType”)
  3.         watchFile.IncludeSubdirectories = False
  4.         watchFile.Path = ConfigurationManager.AppSettings.Item(“WatcherPath”)
  5.         AddHandler watchFile.Changed, AddressOf FileNotification
  6.         AddHandler watchFile.Renamed, AddressOf FileNotification
  7.         AddHandler watchFile.Deleted, AddressOf FileNotification
  8.         watchFile.EnableRaisingEvents = True

The file watcher is implemented using the WCF Callback function. Whenever any change in the specified directory an event is triggered and a callback function is called. The WCF client program will listen to the callback function and update the control. For sample program the changes are formed as XML string and returned in the callback. When the callback function is called the xml is updated to the rich text control of the forms client.

Code Snippet
  1. Public Class NotificationImpl
  2.     Implements CallbackClient.ServiceClient.ICallbackServiceCallback
  3.     Private rtx As RichTextBox
  4.     Public Sub New(ByVal MyRtx As RichTextBox)
  5.         rtx = MyRtx
  6.     End Sub
  7.     Public Sub Callback(ByVal OutXml As String) Implements ServiceClient.ICallbackServiceCallback.Callback
  8.         rtx.AppendText(“——-START: “ & DateTime.Now.ToString(“dd/MMM/yyyy hh:mm:ss”) & “———-“ & Chr(13))
  9.         rtx.AppendText(OutXml)
  10.         rtx.AppendText(Chr(13) & “————-END ————–“ & Chr(13))
  11.     End Sub
  12. End Class

The WCF service is implemented using the NetTcp binding. The attached file contains the WCF service library and the Console Host for the service. The second attachment contains the form client to get the notification. The samples are in VB code

Download the Source code from below links…

Callback Service Code

Callback Client

WCF Service Error Hosting – Adding reference to netTcp binding service error

 

System.InvalidOperationException: Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Registered base address schemes are [http].
   at System.ServiceModel.ServiceHostBase.MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding, UriSchemeKeyedCollection baseAddresses)

image

Metadata contains a reference that cannot be resolved: ‘net.tcp://localhost:8732/Callback.ServiceLibrary/CallbackService/’.
The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was ’00:05:00′.
An existing connection was forcibly closed by the remote host
If the service is defined in the current solution, try building the solution and adding the service reference again.

Resolution:

step 1: Adding the mex metadata to the config solved the issue

Add the below endpoint to the service node

<endpoint address="mex"
                 binding="mexTcpBinding"
                 contract="IMetadataExchange"/>

step 2: Add the Service metadata tag to the service behaviors node

<serviceBehaviors>
        <behavior name="Callback.ServiceLibrary.CallbackServiceBehavior">
          <serviceDebug includeExceptionDetailInFaults="False" />
          <serviceMetadata policyVersion="Policy15"/>
        </behavior>
      </serviceBehaviors>

step 3: Use the url net.Tcp://localhost:8732/mex to add the service reference not the full url

 

Serialize the Data to XML

public static String SerializeInterface(object SerializedObject)
       {
           using (MemoryStream stream = new MemoryStream())
           {
               XmlSerializer serializer = null;
               if (SerializedObject.GetType() == typeof(INTERFACE_ERRORS))
               {
                   serializer = new XmlSerializer(typeof(INTERFACE_ERRORS));
                   INTERFACE_ERRORS o = (INTERFACE_ERRORS)SerializedObject;
                   serializer.Serialize((Stream)stream, o);
               }
               else if (SerializedObject.GetType() == typeof(DETAILS_TO_SUB_SYSTEM))
               {
                   serializer = new XmlSerializer(typeof(DETAILS_TO_SUB_SYSTEM));
                   DETAILS_TO_SUB_SYSTEM details_to_sub_system = (DETAILS_TO_SUB_SYSTEM)SerializedObject;
                   serializer.Serialize((Stream)stream, details_to_sub_system);
               }

               stream.Seek(0L, SeekOrigin.Begin);
               byte[] buffer = new byte[stream.Length];
               int count = stream.Read(buffer, 0, 20);
               while (count < stream.Length)
               {
                   buffer[count++] = Convert.ToByte(stream.ReadByte());
               }

               char[] chars = new char[Encoding.UTF8.GetCharCount(buffer, 0, count)];
               Encoding.UTF8.GetDecoder().GetChars(buffer, 0, count, chars, 0);
               return new string(chars);
           }
       }

XSD.exe Class Generate Error – Datatype missing for sqltypes

 

Select *  FROM dbo.aspnet_applications  FOR XML AUTO, XMLSCHEMA

The xsd generated from sql using the following query(aspnet_applications is the table name) will have the sqltypes imported in the schema. If we use the xsd command line tool to generate a cs class the xsd will through the exception

Error: Error generating classes for schema ‘aspnet_applications’.
  – The datatype ‘
http://schemas.microsoft.com/sqlserver/2004/sqltypes:nvarchar’
is missing.”

If we look at the xsd generated by sql the namespace will point to the sqltypes.xsd uri which xsd.exe could not resolve.

—————–XSD Generated By SQL ————–

<xsd:schema targetNamespace="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:schema="urn:schemas-microsoft-com:sql:SqlRowSet1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified">
  <xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" />
  <xsd:element name="AETSMiMgmtDev.dbo.aspnet_Applications">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="ApplicationName">
          <xsd:simpleType>
            <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreNonSpace IgnoreKanaType IgnoreWidth">
              <xsd:maxLength value="256" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
        <xsd:element name="LoweredApplicationName">
          <xsd:simpleType>
            <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreNonSpace IgnoreKanaType IgnoreWidth">
              <xsd:maxLength value="256" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
        <xsd:element name="ApplicationId" type="sqltypes:uniqueidentifier" />
        <xsd:element name="Description" minOccurs="0">
          <xsd:simpleType>
            <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreNonSpace IgnoreKanaType IgnoreWidth">
              <xsd:maxLength value="256" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

———————END——————

To solve this issue i modified the xsd to include the xsd in the local directory. I navigated to the URL “http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd” , downloaded the full xsd and saved the file as sqltypes.xsd

After saving the sqltypes in a seperate xsd, i modified the original aspnet_applications.xsd like below

—————–Modified XSD to work for xsd.exe————

<xsd:schema targetNamespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" xmlns="Subscribers"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes"
            elementFormDefault="qualified">
  <xsd:include schemaLocation="sqltypes.xsd" />
  <xsd:element name="aspnet_Applications">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="ApplicationName">
          <xsd:simpleType>
            <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreNonSpace IgnoreKanaType IgnoreWidth">
              <xsd:maxLength value="256" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
        <xsd:element name="LoweredApplicationName">
          <xsd:simpleType>
            <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreNonSpace IgnoreKanaType IgnoreWidth">
              <xsd:maxLength value="256" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
        <xsd:element name="ApplicationId" type="sqltypes:uniqueidentifier" />
        <xsd:element name="Description" minOccurs="0">
          <xsd:simpleType>
            <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreNonSpace IgnoreKanaType IgnoreWidth">
              <xsd:maxLength value="256" />
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

——————————END————-

The modified tag is in red bold color. Remember the downloaded sqltypes.xsd is in the same directory as the aspnet_applications.xsd
Now if we run xsd.exe aspnet_applications.xsd /c

the class generation will be successful

WCF Service – A name was started with an invalid character. Error processing resource

Error Details:

The XML page cannot be displayed

Cannot view XML input using XSL style sheet. Please correct the error and then click the Refresh button, or try again later.


A name was started with an invalid character. Error processing resource

http://SENWIN2008/WCF/Service/’

<%@ ServiceHost Language="C#" Debug="true" Service="Service Name" CodeBehind="Service.svc.cs" %>

Resolution

  1. Check whether the IIS site is configured for .NET 2.0, in the ASP.NET tab of the properties, in some cases the ASP.NET will be 1.1 reference.
  2. If the above is not solved, may be the order of installation of .NET is wrong. Always need to install IIS and then .NET 3.5. If thats the case run the ServiceModelReg.exe from the framework folder this should solve the issue.

Class to Validate XML Against XSD

Recently i was involved in programming generic interface for Submitting PO. I came across the XSD concept of programming. I used the XSD to validate xml passed from different sub system and serialize the data.

Below is the sample code to validate the Xml against Xsd

/////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Schema;
using System.Xml;
using System.IO;

namespace XSDValidation
{
    public static class POXsdValidation
    {
        private static string ErrorMessage;

public enum XmlType
    {
        XSD1,
        XSD2
    }

        public static string XsdError
        {
            get
            {
                return ErrorMessage;
            }
        }
        /// <summary>
        /// Validates the xml string against the xsd
        /// </summary>
        /// <param name="InputXml">Xml String contains the full xml</param>
        /// <param name="XsdPath">Xsd Path to be validated</param>
        private static void ValidateXmlByPath(string InputXml,string XsdPath)
        {
            StringReader xmlString = new StringReader(InputXml);
            ////StringReader xsdReader = new StringReader(XsdPath);
            ErrorMessage = string.Empty;
            ////XmlReader XsdReader = XmlReader.Create(xsdReader);

            //// Create the XmlSchemaSet class.
            XmlSchemaSet sc = new XmlSchemaSet();

            //// Add the schema to the collection.
            sc.Add(null, XsdPath);

            //// Set the validation settings.
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas = sc;
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

            //// Create the XmlReader object.
            XmlReader reader = XmlReader.Create(xmlString, settings);

            //// Parse the file.
            while (reader.Read())
            {
            }
        }
        /// <summary>
        /// Validates the xmlreader content against xsd
        /// </summary>
        /// <param name="InputXml">Xml Reader</param>
        /// <param name="XsdPath">XSD Path</param>
        private static void ValidateXml(XmlReader InputXml, string XsdPath)
        {
            ////StringReader xmlString = new StringReader(InputXml);
            ////StringReader xsdReader = new StringReader(XsdPath);
            ErrorMessage = string.Empty;
            ////XmlReader XsdReader = XmlReader.Create(xsdReader);

            //// Create the XmlSchemaSet class.
            XmlSchemaSet sc = new XmlSchemaSet();

            //// Add the schema to the collection.
            sc.Add(null, XsdPath);

            //// Set the validation settings.
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationType = ValidationType.Schema;
            settings.Schemas = sc;
            settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

            //// Create the XmlReader object.
            XmlReader reader = XmlReader.Create(InputXml, settings);

            //// Parse the file.
            while (reader.Read())
            {
            }
        }
        /// <summary>
        /// Validates the Xml Against xsd
        /// </summary>
        /// <param name="InputXml">Input Xml String to Validate</param>
        /// <param name="InputType">Type of Validation</param>
        public static void ValidateXml(string InputXml,XmlType InputType)
        {
            string PathWCF = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
            //// Add the schema to the collection.
            switch (InputType)
            {
                case XML1:
                    PathWCF += "\\bin\\schemas\\XSD1.xsd";
                    break;
                case XML2:
                    PathWCF += "\\bin\\schemas\\XSD2.xsd";
                    break;
            }

            ValidateXmlByPath(InputXml, PathWCF);
        }
        /// <summary>
        /// Callback function for Validate Schema
        /// </summary>
        /// <param name="sender">Object value</param>
        /// <param name="e">Validation message object</param>
        private static void ValidationCallBack(object sender, ValidationEventArgs e)
        {
            ErrorMessage += "<Validation>" +  e.Message + "</Validation>" ;
        }
    }
}

WCF DataService with Custom Function and parameter

namespace Senthamil.Sample

{
    public class PORSS : DataService<ModelEntities>
    {
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
            // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
            // Examples:
            config.SetEntitySetAccessRule(“RSS_STATUS”, EntitySetRights.AllRead);
            config.SetServiceOperationAccessRule(“MyFunction”, ServiceOperationRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }

        [WebGet]
        public IQueryable<RSS_STATUS> MyFunction(string RefNumb)
        {
            ModelEntities MySource = new ModelEntities();
            return from c in MySource.RSS_STATUS
                   where c.SUB_SYSTEM_NUMBER == RefNumb
                   select c;
        }
    }
}

This version of SQL Server in use does not support datatype datetime2

I got this strange issue today, and was struggling to fix this. This issue is related to the SQL 2008 and 2005 compatibility. I had a local machine with SQL 2008, but the Dev environment is with SQL 2005. When i generated the Entities using EF in my local machine it had marked it with 2008 version. When deployed to 2005 the issue was reported.

To fix:

Open the .edmx file using the XML editor option and look for the attribute ProviderManifestToken=”2008″ and change it to 2005 and save. Build and deploy it works.

image

Fill similar objects property by reflection

foreach (PropertyInfo SourceProp in SourcePO.GetType().GetProperties())
           {
               if (SourceProp != null)
               {
                   PropertyInfo TargetProp = TargetPO.GetType().GetProperty(SourceProp.Name.ToUpper());
                   if (TargetProp != null && TargetProp.CanWrite)
                   {
                       object SourcePropValue = SourceProp.GetValue(SourcePO, null);
                       TargetProp.SetValue(TargetPO, SourcePropValue, null);
                   }
               }
           }