Technical Insights: Azure, .NET, Dynamics 365 & EV Charging Architecture

Category: .NET Page 4 of 5

Dotnet general

Resolve URL functions

This snippet code is credited to Scott’s Hanselman, This Resolve URL function is used where you want to implement it on your business layer.

Methods:


        #region "Image URL helpers"

        public static string ResolveUrl(string originalUrl)
        {
            if (originalUrl == null)
                return null;
            // *** Absolute path - just return
            if (originalUrl.IndexOf("://") != -1)
                return originalUrl;
            // *** Fix up image path for ~ root app dir directory
            if (originalUrl.StartsWith("~"))
            {
                string newUrl = "";
                if (System.Web.HttpContext.Current != null)
                    newUrl = System.Web.HttpContext.Current.Request.ApplicationPath + originalUrl.Substring(1).Replace("//", "/");
                else  // *** Not context: assume current directory is the base directory
                    throw new ArgumentException("Invalid URL: Relative URL not allowed.");
                // *** Just to be sure fix up any double slashes
                return newUrl;
            }
            return originalUrl;
        }

        /// Works like Control.ResolveUrl including support for ~ syntax
        /// but returns an absolute URL.
        /// 
        /// Any Url, either App relative or fully qualified
        /// if true forces the url to use https
        /// 
        public static string ResolveServerUrl(string serverUrl, bool forceHttps)
        {    // *** Is it already an absolute Url?
            if (serverUrl.IndexOf("://") > -1)
                return serverUrl;
            // *** Start by fixing up the Url an Application relative Url
            string newUrl = ResolveUrl(serverUrl);
            Uri originalUri = System.Web.HttpContext.Current.Request.Url;
            newUrl = (forceHttps ? "https" : originalUri.Scheme) + "://" + originalUri.Authority + newUrl;
            return newUrl;
        }

        /// 
        /// This method returns a fully qualified absolute server Url which includes
        /// the protocol, server, port in addition to the server relative Url.
        ///
        /// It work like Page.ResolveUrl, but adds these to the beginning.
        /// This method is useful for generating Urls for AJAX methods
        /// 
        /// Any Url, either App relative or fully qualified
        /// 
        public static string ResolveServerUrl(string serverUrl)
        {
            return ResolveServerUrl(serverUrl, false);
        }

        #endregion

Usage:

 sb.AppendFormat("

", row.WidgetItemClass); sb.AppendFormat("More Info", ProductsService.GetProductUrl(row.ProductID), ResolveServerUrl("~/GetWhiteLabelFile.aspx?whiteLabelFileID=" + row.WidgetItemLinkImageID.ToString())); sb.AppendFormat("

");

Upload Multiple Files to FTP in .NET

I’ve played around with FTP couple of weeks back. My application is required to feed FTP folder with 1000+ files daily. I’ve been googling around and I found one of the methods is to use WebApplication so I decided to put this WebApplication method to upload while iterating every single files in the directory. After 5 files, it keeps giving me error The remote server returned an error: (503) Bad sequence of commands. Strangely the only the first 4 files always uploaded successfully, my thought was the FTP server forcely terminated the connection which is right. After googling I found that we should set KeepAlive property to false which means new connection is always created instead of maintained but unfortunately WebClient class doesn’t have KeepAlive property. Finally, I’ve come up with this code which solves my issue in uploading 1000+ files one after the other by doing Asynchronous Upload

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;
using System.IO;

namespace Helpers
{
    public class FtpHelpers
    {
        public class FtpState
        {
            private ManualResetEvent wait;
            private FtpWebRequest request;
            private string fileName;
            private Exception operationException = null;
            string status;

            public FtpState()
            {
                wait = new ManualResetEvent(false);
            }

            public ManualResetEvent OperationComplete
            {
                get { return wait; }
            }

            public FtpWebRequest Request
            {
                get { return request; }
                set { request = value; }
            }

            public string FileName
            {
                get { return fileName; }
                set { fileName = value; }
            }
            public Exception OperationException
            {
                get { return operationException; }
                set { operationException = value; }
            }
            public string StatusDescription
            {
                get { return status; }
                set { status = value; }
            }
        }

        public void AsynchronousUpload(string destinationPath, string sourcePath, string userName, string password)
        {
            // Create a Uri instance with the specified URI string.
            // If the URI is not correctly formed, the Uri constructor
            // will throw an exception.
            ManualResetEvent waitObject;

            Uri target = new Uri(destinationPath);
            string fileName = sourcePath;
            FtpState state = new FtpState();
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(target);
            request.Method = WebRequestMethods.Ftp.UploadFile;
            request.KeepAlive = false;
            request.Proxy = null;

            // This example uses anonymous logon.
            // The request is anonymous by default; the credential does not have to be specified.
            // The example specifies the credential only to
            // control how actions are logged on the server.

            if (!(string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(password)))
            {
                request.Credentials = new NetworkCredential(userName, password);
            }

            // Store the request in the object that we pass into the
            // asynchronous operations.
            state.Request = request;
            state.FileName = fileName;

            // Get the event to wait on.
            waitObject = state.OperationComplete;

            // Asynchronously get the stream for the file contents.
            request.BeginGetRequestStream(
                new AsyncCallback(EndGetStreamCallback),
                state
            );

            // Block the current thread until all operations are complete.
            waitObject.WaitOne();

            // The operations either completed or threw an exception.
            if (state.OperationException != null)
            {
                throw state.OperationException;
            }

        }

        private static void EndGetStreamCallback(IAsyncResult ar)
        {
            FtpState state = (FtpState)ar.AsyncState;

            Stream requestStream = null;
            // End the asynchronous call to get the request stream.
            try
            {
                requestStream = state.Request.EndGetRequestStream(ar);
                // Copy the file contents to the request stream.
                const int bufferLength = 2048;
                byte[] buffer = new byte[bufferLength];
                int count = 0;
                int readBytes = 0;
                FileStream stream = File.OpenRead(state.FileName);
                do
                {
                    readBytes = stream.Read(buffer, 0, bufferLength);
                    requestStream.Write(buffer, 0, readBytes);
                    count += readBytes;
                }
                while (readBytes != 0);
                // IMPORTANT: Close the request stream before sending the request.
                requestStream.Close();
                // Asynchronously get the response to the upload request.
                state.Request.BeginGetResponse(
                    new AsyncCallback(EndGetResponseCallback),
                    state
                );
            }
            // Return exceptions to the main application thread.
            catch (Exception e)
            {
                state.OperationException = e;
                state.OperationComplete.Set();
                return;
            }

        }

        // The EndGetResponseCallback method
        // completes a call to BeginGetResponse.
        private static void EndGetResponseCallback(IAsyncResult ar)
        {
            FtpState state = (FtpState)ar.AsyncState;
            FtpWebResponse response = null;
            try
            {
                response = (FtpWebResponse)state.Request.EndGetResponse(ar);
                response.Close();
                state.StatusDescription = response.StatusDescription;
                // Signal the main application thread that
                // the operation is complete.
                state.OperationComplete.Set();
            }
            // Return exceptions to the main application thread.
            catch (Exception e)
            {
                state.OperationException = e;
                state.OperationComplete.Set();
            }
        }

    }
}

Usage:

#Region "Properties"

    Private _ftpUploader As FtpHelpers = Nothing

    Private ReadOnly Property FtpUploader() As FtpHelpers
        Get
            If (_ftpUploader Is Nothing) Then
                _ftpUploader = New FtpHelpers()
            End If

            Return _ftpUploader
        End Get
    End Property

#End Region

Private Sub ProcessFilesToFTP()

        ' make a reference to a directory
        Dim di As New IO.DirectoryInfo(ConfigurationManager.AppSettings("OutputZIPDirectory"))
        Dim jobFiles As IO.FileInfo() = di.GetFiles()

        Console.WriteLine(String.Format("FTP Location: {0}", ConfigurationManager.AppSettings("ftplocation")))

        'list the names of all files in the specified directory
        For Each jobFile As IO.FileInfo In jobFiles

            'process only zip file
            If (jobFile.FullName.Contains("zip")) Then
                Console.WriteLine(String.Format("Upload file {0}", jobFile.Name))

                FtpUploader.AsynchronousUpload(ConfigurationManager.AppSettings("ftplocation") + "/" + jobFile.Name, jobFile.FullName, _
                                   ConfigurationManager.AppSettings("ftpuser"), _
                                   ConfigurationManager.AppSettings("ftppassword"))

            End If

        Next

        Console.WriteLine(String.Format("XML files has been uploaded to {0}", ConfigurationManager.AppSettings("ftplocation")))
    End Sub

The drawback with this code is in the FTP connection where the connection always reinitialized for every single file.

SQL Methods in LINQ

I’m trying to implement DateDiff in LINQ. I would like to get all records with the same date and ignoring the timestamp.

Here is my code snippet which doesn’t work

 public int tblExpReceiptFileUniqueID(string chCreateStaffCode, string vcFileName,
                                                long intFileSize, DateTime? sdCreateDate)
        {
            var expReceiptFile = from ef in DataContext.tblExpReceiptFiles orderby ef.intFileID
                                 where ef.chCreateStaffCode == chCreateStaffCode
                                 && ef.vcFileName == vcFileName
                                 && ef.bintFileSize == intFileSize
                                 && ((DateTime)ef.sdCreateDate).Date == sdCreateDate.Value.Date
                                 select ef;

            tblExpReceiptFile expReceiptFileRec = expReceiptFile.First();

            return expReceiptFileRec.intFileID;
        }

I’m trying to cast the column to “DateTime” and use the “Date” property but I got this error
“The Member ‘System.DateTime.Date’ has no supported translation to SQL”

I thought of “DATEDIFF” function in SQL server and I’m trying to get my head around in implementing this using LINQ and I found that we can use a library called “SQLClient”

using System.Data.Linq.SqlClient;

Code Snippet which is working

    public int tblExpReceiptFileUniqueID(string chCreateStaffCode, string vcFileName,
                                                long intFileSize, DateTime? sdCreateDate)
        {
            var expReceiptFile = from ef in DataContext.tblExpReceiptFiles orderby ef.intFileID
                                 where ef.chCreateStaffCode == chCreateStaffCode
                                 && ef.vcFileName == vcFileName
                                 && ef.bintFileSize == intFileSize
                                 && SqlMethods.DateDiffDay(ef.sdCreateDate, sdCreateDate.Value.Date) == 0
                                 select ef;

            tblExpReceiptFile expReceiptFileRec = expReceiptFile.First();

            return expReceiptFileRec.intFileID;
        }

Convert DataTable to CSV Function

This is the class that you can use to create a CSV file from DataTable. Basically what it does is to iterate each column and row in datatable and separate them with comma.

Class/Function:

using System;
using System.Data;
using System.IO;
using System.Text;
using System.Web;

namespace BusinessLayer
{
    public class CSVBuilder
    {
        public static string BuildCSVDocument(DataTable table)
        {
            StringBuilder   builder = new StringBuilder();
            DataColumn      col;

            // append header
            for (int index = 0; index < table.Columns.Count; index++)
            {
                col = table.Columns[index];
                builder.AppendFormat("{0},", col.ColumnName);
            }

            builder.AppendLine();

            // append rows
            foreach (DataRow row in table.Rows)
            {
                object[] values = row.ItemArray;

                for (int index = 0; index < values.Length; index++)
                {
                    object value = row[index];
                    string valueString;

                    if (value is DateTime)
                    {
                        valueString = Convert.ToDateTime(value).ToString("dd/MM/yyyy hh:mm");
                    }
                    else if (value is string)
                    {
                        valueString = value.ToString().Replace("'", "`").Replace(",", "");
                    }
                    else
                    {
                        valueString = value.ToString();
                    }

                    builder.AppendFormat("{0},", valueString);
                }

                builder.AppendLine();
            }

            return builder.ToString();
        }

        public static void StreamCSV(DataTable table, HttpResponse response, string fileName)
        {
            // convert the extract to CSV
            string csv = BuildCSVDocument(table);

            // Send it to browser
            response.ClearContent();
            response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
            response.ContentType = "text/csv";

            // Write to the stream
            StreamWriter sw = new StreamWriter(response.OutputStream);
            sw.Write(csv);
            sw.Close();

            response.Flush();
            response.Close();
        }
    }
}

Usage

 private void GenerateMyCsv()
    {
        lblErrorOrderID.Visible = false;

        try
        {
            tdsReports.MissingBatchNumberSelectDataTable dtBatch =
                ReportFactory.GetMissingBatch(txtOrderID.Text);

            //display no results returned message
            if (dtBatch.Rows.Count != 0)
            {
               CSVBuilder.StreamCSV(dtBatch , Response, "MyCSV.csv");
            }

        }
        catch (ApplicationException ex)
        {
            lblErrorOrderID.Text = ex.Message;
            lblErrorOrderID.Visible = true;
        }
        catch (Exception ex)
        {
            lblErrorOrderID.Text = ex.Message;
            lblErrorOrderID.Visible = true;
        }
    }

Using Transaction Scope on .NET

Basic Requirements:

1. Have the MSDTC(Distributed Transaction Coordinator) windows service running on your machine
2. Be talking to a SQL 2000 or 2005 Database configured likewise
3. Run this registry script to fix the windows XP SP2 that was causing MSDTC to fail (save as “.reg”)

Registry Script

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\RPC]
"RestrictRemoteClients"=dword:00000000

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Rpc\Internet]
"Ports"=hex(7):31,00,30,00,32,00,35,00,2d,00,31,00,30,00,35,00,35,00,00,00,00,\
  00
"PortsInternetAvailable"="Y"
"UseInternetPorts"="Y"

You can create a class/library to wrap the transaction code
Code:

using System;
using System.Data;
using System.Transactions;

namespace BusinessLayer
{
    public class TransactionScopeWrapper : IDisposable
    {
        private TransactionScope _scope = null;

        public TransactionScopeWrapper()
        {
            if (ConfigHelper.UseTransactionScope)
            {
                int timeout = ConfigHelper.TransactionTimeoutMinutes;

                if (timeout == int.MinValue)
                {
                    timeout = 10;
                }

                _scope = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, timeout, 0));
            }
        }

        public void Complete()
        {
            if (_scope != null)
            {
                _scope.Complete();
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (_scope != null)
            {
                _scope.Dispose();
            }
        }

        #endregion
    }
}

Usage of the wrapper:

public void CancelAuction(int auctionid)
        {
            using (TransactionScopeWrapper scope = new TransactionScopeWrapper())
            {
                tdsAuction.AuctionDataTable auctionTable = AuctionAdapter.AuctionSelect(auctionid);

                if (auctionTable.Rows.Count > 0)
                {
                    tdsAuction.AuctionRow auctionRow = auctionTable.Rows[0] as tdsAuction.AuctionRow;

                    auctionRow.AuctionStatusID = (int)AuctionStatusEnum.Cancelled;
                    AuctionAdapter.Update(auctionRow);

                    // return the Stock to inventory
                    if (auctionRow.IsAuction)
                    {
                        InventoryData.InventoryReturnLotsCancelAuction(auctionid);
                    }
                    else
                    {
                        InventoryData.InventoryReturnLotsForDeal(auctionid);
                    }
                }

                scope.Complete();
            }
        }

the server committed a protocol violation section= responsestatusline

I’ve got this error and try to spend almost an hour to resolve this:

“the server committed a protocol violation section= responsestatusline” when I tried to get the response back from the payment gateway. It happens when you send HTTP Request one after another on the same page. The solution is to add unsafeheaderparsing to true in web.config and to seet keepAlive property to false from the http request it self

Web.Config


		
			
		
		
			
		
    
      
        
      
    
  

Calling Code:

   Private Function SendXML(ByVal strSend As String) As Boolean
        Dim blnSuccess As Boolean = False
        Dim objSendXML As XmlDocument
        Dim objRequest As HttpWebRequest
        Dim mywriter As StreamWriter
        Dim objResponse As HttpWebResponse
        Dim objReturnedXML As XmlDataDocument
        Dim objElementRoot As XmlElement
        Dim objElementTransaction As XmlNode
        Dim objElementCreditCardInfo As XmlNode
        Dim x As XmlNode

        Dim strApproved As String = String.Empty
        Dim blnCreditCardInfo As Boolean = False

        ' Must reset the variable incase of error
        Me._Paid = False

        objSendXML = New XmlDocument
        objRequest = WebRequest.Create(strPaymentURL)


        'if it is using proxy/behind proxy
        If (UseProxy And Not (String.IsNullOrEmpty(ProxyServer))) Then
            objRequest.Proxy = New System.Net.WebProxy(ProxyServer, True)

            'if there is credential
            If (UseDefaultCredential) Then
                objRequest.Proxy.Credentials = CredentialCache.DefaultCredentials
            Else
                objRequest.Proxy.Credentials = New NetworkCredential(UserName, Password)
            End If

        End If

        objRequest.Method = "POST"
        objRequest.ContentLength = strSend.Length
        objRequest.ContentType = "text/xml"

        'to solve protocol violation problem
        objRequest.KeepAlive = False

Iterate by Index in DataTable

This post will explain how to iterate through datatable and how to get value based on index.


//This function is used to iterate through datatable
private void GetAllRows(DataSet ds){
   // iterate through table in the DataSet
get the values of each row.

   foreach(DataTable currTable in ds.Tables){
      // iterate through row
      foreach(DataRow currRow in currTable.Rows){
//iterate through column
         foreach(DataColumn currCol in currTable.Columns){
            Console.WriteLine(currRow[currCol]);
         }
       }
   }
}

//This one line of code is used to access based on row and column index.
currTable.Rows[0][1]      --- represents the value in first row and second

Enums with description in c#

Sometime when we have Enum , we want to use it /bind it on the list as well with a better description/ word. With this method you can bind enum to a list which display its description but store its value as well.This is very useful function.

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Reflection;
using System.ComponentModel;

public class Enums
    {
        #region helpers
        public static string GetEnumDescription(Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());
            DescriptionAttribute[] attributes =
              (DescriptionAttribute[])fi.GetCustomAttributes
              (typeof(DescriptionAttribute), false);
            return (attributes.Length > 0) ? attributes[0].Description : value.ToString();
        }

        public static T Parse(string input)
        {
            return (T)Enum.Parse(typeof(T), input);
        }
        #endregion

        #region enums
        public enum ResultsType
        {
            [Description("Featured Products")]
            FeaturedProducts,
            [Description("New Products")]
            NewStock,
            CategoryResults,
            [Description("Specials")]
            Specials,
            Brand,
            Row1,
            Row2,
            Row3,
            [Description("This Weeks Specials")]
            ThisWeeksSpecials,
            [Description("Top 10 Best Sellers")]
            Top10BestSellers,
            [Description("Special Offers")]
            SpecialOffers,
            [Description("Buy 1 Get 1 Free")]
            Buy1Get1Free,
            [Description("Half Price Bargains")]
            HalfPriceBargains,
            [Description("Top Sellers")]
            TopSellers,
            [Description("Summer Specials")]
            SummerSpecials,
            [Description("CUSTOMERS WHO BOUGHT THIS ALSO BOUGHT")]
            AlsoBought,
            [Description("Related Products")]
            Upsell
        }

          public enum ReportType
         {
            [Description("Monthly Sales Report")]
            MonthySalesReport = 1,
            [Description("Dispatched Orders Report")]
            DispatchedOrdersReport = 2,
            [Description("Order Report")]
            OrderReport = 3
         }

#endregion

}

This is how you bind it

Private Sub PopulateReportType()

        ddlReportType.Items.Clear()
        ddlReportType.Items.Add(New ListItem(Enums.GetEnumDescription(Enums.ReportType.MonthySalesReport), Convert.ToInt32(Enums.ReportType.MonthySalesReport)))
        ddlReportType.Items.Add(New ListItem(Enums.GetEnumDescription(Enums.ReportType.DispatchedOrdersReport), Convert.ToInt32(Enums.ReportType.DispatchedOrdersReport)))
        ddlReportType.Items.Add(New ListItem(Enums.GetEnumDescription(Enums.ReportType.OrderReport), Convert.ToInt32(Enums.ReportType.OrderReport)))

    End Sub

Raise Event in User Control

I need to create a payment gateway user control that will be used accross all of the modules. This user control should be as simple as doing the transaction ONLY. So what I need to do is to let the host/page container knows whether the transaction is succeeded or not, if it is succeeded then the rest of the logic will be handled on ASPX page.

In order to do so I need to create an event on the user control that will be bubbled up to the page container/host. This sample might not be the best solution but it works perfectly for my needs and only requires several lines of code.

Write this in your user control including declaration(signature) of parameter that you want to pass

Partial Class usercontrols_MyPaymentGateway
    Inherits System.Web.UI.UserControl

#Region "Property"

    ''' 
    ''' this is an event for process status
    ''' 
    ''' 
    Public Event getProcessStatus(ByVal isPaid As Boolean)

Write this in your user control where you want to raise the event and pass the parameter

     RaiseEvent getProcessStatus(True)

Write this in your page container(Create an Event handler to handle your user control events) (NOTE: paymentGateway is the name of your user control)

 ''' 
    ''' event handler to the payment gateway controls
    ''' 
    ''' 
    ''' 
    Private Sub paymentProcessed(ByVal isPaid as boolean) Handles paymentGateway.getProcessStatus

        If (paymentGateway.IsPaid) Then
            ltMessage.Text = "Payment Successful " + paymentGateway.ResponseMessage

            'if it is paid then we need to clear the remaining text boxes
            paymentGateway.ClearFields()
        Else
            ltMessage.Text = "Payment Failed " + paymentGateway.ResponseMessage
        End If

    End Sub

How to remove checked item in Checked Box List

At the moment, I’m learning towards win development. I got a very simple problem which is “Removing checked item on checked box list”. The first code below is throwing an error since you try to delete an item then on the postback it will reset the index. The real solution is on the second code

//this code is throwing an error about the index position
 private void btnRemove_Click(object sender, EventArgs e)
        {
            foreach (SMSData item in chkSmsList.CheckedItems)
            {
                chkSmsList.Items.Remove(item);
            }
        }

Fix

//this is the code which is working perfectly, basically this code always looking into the first item on the "CheckedItems" Stack
  private void btnRemove_Click(object sender, EventArgs e)
        {
            while (chkSmsList.CheckedItems.Count > 0)
            {
                chkSmsList.Items.Remove(chkSmsList.CheckedItems[0]);
            }
        }

Page 4 of 5

Powered by WordPress & Theme by Anders Norén