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

Month: September 2008 Page 2 of 3

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

Paging through strored procedure in sql server

This is very important for the most web developers. This stored procedure accept parameter of page index and page size. By using this paging, you don’t need to store everything in your viewstate which in the end will cause performance suffer. This will load up the necessary result based on the page index and page size and it uses row number to put the number in each row.

Datagrid needs to use custom paging = true as well as virtualitem count to produce the number for paging.

Datagrid in ASPX Page


            
                
                
                
                    
                    
                    
                    
                    
                    
                
                
                
            

Code Behind

//function to do the paging itself
  private void LoadContent(int pageIndex)
    {
        _presenter.GetContentSubmissionSelect(pendingStatusID, pageIndex, PAGE_SIZE);

        if (GetContentSubmissionSelect.Rows.Count > 0)
        {
            lblNoContent.Visible = false;

            dgTaskList.Visible = true;
            dgTaskList.AllowCustomPaging = true;
            dgTaskList.AllowPaging = true;
            dgTaskList.PageSize = PAGE_SIZE;
            _presenter.GetContentSubmissionCount(pendingStatusID);

            dgTaskList.VirtualItemCount = Convert.ToInt32(GetContentSubmissionCount.Rows[0][0]);
            dgTaskList.DataSource = GetContentSubmissionSelect;
            dgTaskList.CurrentPageIndex = pageIndex;
            dgTaskList.DataBind();
        }
        else
        {
            dgTaskList.Visible = false;
            lblNoContent.Visible = true;
        }
    }

//handle the page index changed
    protected void dgTaskList_PageIndexChanged(object sender, DataGridPageChangedEventArgs e)
    {
        LoadContent(e.NewPageIndex);
    }

SQL Stored Procedure
We need to have two query where one to get the number of records and the other one is to get the actual result it self
To get the query/actual result

CREATE PROCEDURE uspContentSubmissionSelect
(
	@statusID int = NULL,
	@PageIndex int,
	@PageSize int
)
AS
	SET NOCOUNT ON;
SELECT
	o.Id, o.ContentSubmission_id, o.AppointmentId,
	o.Title, o.StatusName
FROM
	(
		SELECT
			r.ID, r.contentSubmission_id, r.AppointmentId,
			r.Title, s.StatusName,
			ROW_NUMBER() OVER (ORDER BY r.ID DESC) as RowNumber
		FROM
			MyInternet.ContentSubmissionRef r
		INNER JOIN
			MyInternet.Status s
		ON
			s.Id = r.StatusID
		AND
			((@StatusID IS NULL) OR (s.ID = @statusID))
	) o
WHERE
	o.RowNumber BETWEEN (@PageIndex * @PageSize + 1) AND ((@PageIndex * @PageSize) + @PageSize)
ORDER BY RowNumber
GO


To get the record count

CREATE PROCEDURE [dbo].[uspContentSubmissionCount]
(
	@statusID int = NULL
)
AS
	SET NOCOUNT ON;

		SELECT
			COUNT(*) AS TotalRow
		FROM
			MyInternet.ContentSubmissionRef r
		INNER JOIN
			MyInternet.Status s
		ON
			s.ID = r.StatusID
		AND
			((@StatusID IS NULL) OR (s.ID = @statusID))

Invalid postback or call argument

It’s quite often I have this error because of the content has been changed during postback or because of the control id. I’ve read most of the article suggested to disable the event validation by putting this on the page which is loosen up the security of that particular page. I found the other method without need to change the EnableEventValidation to false. What i found is that you can reregister your control on the render method
VB.NET

Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)

Register(Me)
MyBase.Render(writer) End Sub

Private Sub Register(ByVal ctrl As Control)
For Each c As Control In ctrl.Controls

Register(c)

Next

Page.ClientScript.RegisterForEventValidation(ctrl.UniqueID)

End Sub

C#

protected override void Render(HtmlTextWriter writer)

{
Register(this);base.Render(writer);

}
private void Register(Control ctrl)

{
foreach (Control c in ctrl.Controls)

Register(c);

Page.ClientScript.RegisterForEventValidation(ctrl.UniqueID);

}

How to find a query under a particular stored procedure in SQL Server

I’ve got a question this morning about how to find a particular query in a huge list of stored procedure. It’s not that hard, what you need to do is to use SYS object and sys.procedures basically contains all the stored procedure under the active database that you are using. This is the query that you can use to find a keyword product in any stored procedure

SELECT ROUTINE_NAME, ROUTINE_DEFINITION
    FROM INFORMATION_SCHEMA.ROUTINES
    WHERE ROUTINE_DEFINITION LIKE '%product%'
    AND ROUTINE_TYPE='PROCEDURE'

And the query below is used to find the stored procedure name that match with what you are looking for

SELECT *
FROM sys.procedures where OBJECT_DEFINITION(object_id) LIKE '%product%'

UPDATE:
How to find all the triggers on your Database

SELECT tbl1.[name] TableName, tbl0.[name] TriggerName,
CASE
WHEN tbl1.deltrig = tbl0.id  THEN 'OnDelete'
WHEN tbl1.instrig = tbl0.id THEN 'OnInsert'
WHEN tbl1.updtrig = tbl0.id THEN 'OnUpdate'
END 'Operation Type', tbl1.*,tbl0.*
FROM sysobjects tbl0 JOIN sysobjects tbl1 ON tbl0.parent_obj = tbl1.[id] WHERE tbl0.xtype='TR'

Divide by zero error occured in SQL Server

I tried to create an average in sql server by dividing two figures. Once I got the error of “Divide by zero error occured”, this is caused by dividing the figure by null value, to handle the error we can use “NULLIF”

DECLARE @ThisMonthAvg decimal(8,2)
SET @ThisMonthAvg = @ThisMonthPlayers / NULLIF(@ThisMonthEvents, 0)

DECLARE @LastMonthAvg decimal(8,2)
SET @LastMonthAvg = @LastMonthPlayers / NULLIF(@LastMonthEvents, 0)

DECLARE @ThisYearAvg decimal(8,2)
SET @ThisYearAvg = @ThisYearPlayers / NULLIF(@ThisYearEvents, 0)

DECLARE @LastYearAvg decimal(8,2)
SET @LastYearAvg = @LastYearPlayers / NULLIF(@LastYearEvents, 0)

Create hyperlink column in gridview or datagrid

Sometimes when you display the data on the datagrid or gridview , you want to create some link. let’s say when you displaying your user detail data in the grid. you want the user to be able to click the link in email column that automatically open microsoft outlook for you. You also would like to avoid writing some string replacement or creating a function in rowbound event. This is the easiest way to do it. Edit the column and add this into DataFormatString

{0:G}

this can be used to pass some variable from the fields(query string) to some address.

Error code 0x8013134b when debugging ASP.NET

Auto-attach to process ‘[2440] w3wp.exe’ on machine ‘…’ failed. Error code 0x8013134b. This problem is most likely occurred because I have two .NET framework installed in my PC (v1.14322 and v2.0).

To fix this problem:

• Open IIS (inetmgr)
• Right click on the web site with the problem
• Click the ASP.NET tab
• Change the ASP.NET version from 2.something to 1.14322 in the dropdown(or vice versa) and debugging works again

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

key event handler that compatible with all browsers using javascript

This might be useful for web developer which wants to have one key event handler that compatible with all browsers.


document.onkeyup = KeyCheck;

function KeyCheck(e)
{
  //this is used for cross browser
  var KeyID = (window.event) ? event.keyCode : e.keyCode;

  switch(KeyID)
   {

   case 13:
    checkPostCodeSelection();
    break;
      }
}

Page 2 of 3

Powered by WordPress & Theme by Anders Norén