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

Category: .NET

Dotnet general

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]);
            }
        }

Record/Row Filter in DataTable

When I have a smaller rows return from my sql stored procedure, I tend to think of not recreating another stored procedure to do filtering or to use optional parameter. My idea is to do filtering from the code base and not recreating/adding the stored procedure.

The idea was to create a generic stored procedure without any filter and apply the filter from the code base. The example given is by applying filter to dataset and then after that add the datatable to dataset and then cast it back again to the datatable.

  public tdsEvent.EventSummaryDataTable TodayEventSummaryFilter(string filter)
        {
            tdsEvent.EventSummaryDataTable table = TodayEventSummaryCache();
            DataRow[] rows = table.Select(filter); //apply the filter first

            if (rows.Length != 0)
            {
                DataSet ds = new DataSet();

                tdsEvent.EventSummaryDataTable eventTable = new tdsEvent.EventSummaryDataTable();
                ds.Tables.Add(eventTable); // add to the filter
                ds.Merge(rows, false, MissingSchemaAction.Ignore);
                // cast it back to the data table
                table = ds.Tables[0] as tdsEvent.EventSummaryDataTable;
            }
            else
            {
                table = new tdsEvent.EventSummaryDataTable();
            }

            return table;
        }

This is the alternative code which doing the same thing as above

Dim table as tdsEvent.EventSummaryDataTable = TodayEventSummaryCache()
//create dataview instance based on datatable

dim dv as DataView = new DataView(table)

//create the filter to select the valid only
dv.RowFilter = "Valid = 1"

//bind to the grid or repeater
rptEvent.Datasource = dv
rptEvent.DataBind()

Override connection string in TableAdapter with web.config

I found this tip is very useful for me in my day to day coding. Sometimes you create a table adapter in dataset in Data layer project, everything works fine but you will start wondering how to make it configurable or how to use the connection string in my web project which is in web.config.

You don’t want to keep changing it and compile it everytime you change the database right?Ok so what you can do is now to open or to add “settings.cs” which is located in your data layer project and then you can paste this piece of code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Linq.Properties
{

    internal sealed partial class Settings
    {
        #region generated stuff

        public Settings()
        {
            // // To add event handlers for saving and changing settings, uncomment the lines below:
            //
            // this.SettingChanging += this.SettingChangingEventHandler;
            //
            // this.SettingsSaving += this.SettingsSavingEventHandler;
            //
        }

        private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e)
        {
            // Add code to handle the SettingChangingEvent event here.
        }

        private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // Add code to handle the SettingsSaving event here.
        }

        #endregion

        #region ->this override

        public override object this[string propertyName]
        {
            get
            {
                if (propertyName == "scoutsJamboreeConnectionString")
                {
                    return (System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
                }
                return base[propertyName];
            }

            set
            {
                base[propertyName] = value;
            }
        }

        #endregion
    }
}

Dynamic array in VB/VB.NET/ASP

Time to go back to old school ASP, I found that i need to create an array that contains a list of languages from a table in database. I would like to make this array length as many as the number of rows in language table. yes you can do it through keyword of ReDim and Preserve

     <%
                dim objLanguage
                dim languageCount
                dim languageArray()

                languageCount = 0

                set objLanguage = Server.CreateObject("ADODB.Recordset")
                objLanguage.ActiveConnection = MM_CTG_STRING
                objLanguage.Source = "SELECT * FROM Languages"
                objLanguage.CursorType = 0
                objLanguage.CursorLocation = 2
                objLanguage.LockType = 3
                objLanguage.Open()

                WHILE NOT objLanguage.EOF
                    response.Write("

") response.Write(objLanguage("Language")) response.Write("

") ReDim Preserve languageArray(languageCount) languageArray(languageCount) = objLanguage("LanguageID") languageCount = languageCount + 1 objLanguage.MoveNext() WEND objLanguage.Close() Set objLanguage = nothing %>

407 Proxy authentication required

I found this problem when i try to do any of httpweb request behind proxy and i got error of “407 proxy authentication required”. Normally your company has its own proxy server and sometimes you want to call webservice or reading XML from any website or sending xml to payment gateway.

The workaround this is to use proxy properties of your httpwebrequest variable. this is some snippet

         Dim objRequest As HttpWebRequest
         objSendXML = New XmlDocument
         objRequest = WebRequest.Create(strPaymentURL)
         objRequest.Method = "POST"
         objRequest.ContentLength = strSend.Length
         objRequest.ContentType = "text/xml"

        'for development only!!! have to be blocked on production
         objRequest.Proxy = New System.Net.WebProxy("http://proxy-syd:8080", True)
         objRequest.Proxy.Credentials = CredentialCache.DefaultCredentials

Now you can call your webservice or reading xml behind the proxy server

Page 4 of 4

Powered by WordPress & Theme by Anders Norén