Posts

....
Technical Blog for .NET Developers ©

Thursday, November 28, 2013

Bulk eMail

When we are designing processes for sending bulk emails, we have to keep in mind anti-spam filters and its different policies

These are some of the key points to avoid our sent emails going into the spam folder:
- Launch the process from a server with a consistent IP address
- Keep valid reverse DNS records for the IP address(es) from which you send mail, pointing to your domain
- Add headers to identify the precedence of the email as bulk
- Provide a service to the end user can cancel the subscription
- Send emails one by one instead of collecting all recipients in the To property

You can find more information here (Google Bulk Senders Guidelines), and here (Tips for avoiding spam filters)

The code for sending emails repetitively with these specifications is the next

 
    private void sendEmails(List<emailToSend> emailsToSendList)
    {
        string _sender = ConfigurationManager.AppSettings["sender"];
        string _host = ConfigurationManager.AppSettings["host"];
        string _pswd = ConfigurationManager.AppSettings["pswd"];
        string _port = ConfigurationManager.AppSettings["port"];

        foreach (eMailToSend email in emailsToSendList) {

            try 
            {        
                System.Net.Mail.MailMessage mail = new System.Net.Mail.MailMessage();

                mail.From = new MailAddress("no-reply@yourdomain.com", "no reply");

                mail.To.Add(email.Address);
                mail.Subject = "bulk campaign";

                mail.Body = email.HTMLBody;

                mail.BodyEncoding = System.Text.Encoding.UTF8;
                mail.IsBodyHtml = true;

                mail.Headers.Add("Precedence", "bulk");
                mail.Headers.Add("Message-Id", string.Concat("<", 
                                 DateAndTime.Now.ToString("yyMMdd"), ".", 
                                 DateAndTime.Now.ToString("HHmmss"), "@yourdomain.com>"));

                mail.Priority = MailPriority.Low;

                SmtpClient mailClient = new SmtpClient();

                NetworkCredential basicAuthenticationInfo = 
                        new NetworkCredential(_sender, _pswd);
                mailClient.Credentials = basicAuthenticationInfo;
                mailClient.Port = _port;
                mailClient.Host = _host;

                mailClient.Send(mail);
            } 
            catch (Exception ex) 
            {
                logError(ex.Message + " >> " + ex.StackTrace);

                continue;
            }
        }
    }
        



<METHOD SOFTWARE © 2013>

Monday, September 30, 2013

WCF Enable SSL

In order to include HTTPS binding to our REST Services in IIS, we have to set up the service to accept SSL Certificates

We must have installed the Certificate on IIS



Browse to the WCF Rest Service Application, click on SSL Configuration, and set up the service to accept client certificates



Now our service works under HTTPS binding, to enable both protocols, we must write two different endpoints referring the service, and stablish the behavior configuration for http and https

     
    <behavior name="ServiceBehavior">
       <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
         <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>      
    
    <%--...--%>
    
    <bindings>
      <webHttpBinding>
        <binding name="BindHttp" crossDomainScriptAccessEnabled="true">
        </binding>      
        <binding name="BindHttps" crossDomainScriptAccessEnabled="true">
            <security mode="Transport" />
        </binding>
      </webHttpBinding>
    </bindings>
    
    <%--...--%>
    
    <services>
      <service behaviorConfiguration="ServiceBehavior" name="WCFRestService.RestService">
        <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding"
          bindingConfiguration="BindHttp" contract="WCFRestService.IRestService" />      
        <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding"
          bindingConfiguration="BindHttps" contract="WCFRestService.IRestService" />          
      </service>
    </services>
    


<METHOD SOFTWARE ©>

Wednesday, July 24, 2013

WCF Rest Services

When we are designing processes which expose data across multi-platform and systems, we have to consider the implementation of REST Services

REST stands for Representational State Transfer. In RESTful systems, servers expose resources using a URI, and clients access these resources using the four HTTP verbs
GET: used exclusively to retrieve data

DELETE: used for deleting resources

PUT: used to add or change a resource

POST: used to modify and update a resource
In this example, we will develop a REST Service with Xml and Json responses, using WCF, and will make the whole circuit to the call

The first step is beginning a new WCF Application. This is the implementation of the interface with the definition of the service contract

 
	namespace RestWCFService
    {
        [ServiceContract]
        public interface IRestService
        {
            [OperationContract]
            [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Xml,
                BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "getXml/{id}")]
            string XmlElement(string id);

            [OperationContract]
            [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json,
                BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "getJson/{id}")]
            string JsonElement(string id);
        }
    }
    


The next step is implementing the service contract

 
	public class RestService : IRestService
    {
        public string XmlElement(string atomicSymbol)
        {
            return getElement(atomicSymbol);
        }

        public string JsonElement(string atomicSymbol)
        {
            return getElement(atomicSymbol);
        }

        private string getElement(string aSymbol)
        {
            Dictionary<string, string> Elements = getElementsTable();

            if (Elements.Keys.Contains(aSymbol))
                return "the element is " + Elements[aSymbol];
            else
                return "there is no match for " + aSymbol;
        }
    }


Now we have to set up the web.config file, changing the next sections:

 
	<services>
      <service name="RestWCFService.RestService" behaviorConfiguration="ServiceBehavior">
        <endpoint binding="webHttpBinding" contract="RestWCFService.IRestService" 
            behaviorConfiguration="web">
        </endpoint>
      </service>
    </services>
    
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <!-- To avoid disclosing metadata information, set the value below to false 
           and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, 
           set the value below to true. Set to false before deployment 
           to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp helpEnabled="true" faultExceptionEnabled="true"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
- The 'services' section will point to our service contract definition, and the 'behaviors' section will enable the http get method

Now we publish the service and check it from the browser



http://localhost:9479/RestService.svc/getXml/O



http://localhost:9479/RestService.svc/getJson/K



To call this service from the client layer we can make use of jQuery Ajax, the code is the next

 
	function getChemical(atomicSymbol) {

        $.ajax({
            url: "http://localhost:9479/RestService.svc/getJson/" + atomicSymbol,
            type: "GET",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: {},
            processdata: true,
            success: function (response) {

                var element = response.JsonElementResult;
                $('#lblElement').html(element);
            },

            error: function (e) {
                alert(e.status + ". " + e.statusText);
            }
        });
    }





<METHOD SOFTWARE © 2013>

Saturday, July 20, 2013

Adding HTML5 Intellisense

When we develop web applications with HTML5 API, we can add HTML5 Intellisense, here is the link to download the installer for Visual Studio and Visual Web Developer 2010 and 2008

HTML 5 Intellisense for Visual Studio 2010 and 2008

We just have to install and the option for HTML5 validation code will appear automatically in our tool bar

Now we will see how the Intellisense displays with HTML5 tags




<METHOD SOFTWARE © 2013>

Wednesday, May 29, 2013

Serialization

Serialization is the act of taking an in-memory object or object graph (set of objects that reference each other) and flattening it into a stream of bytes or XML nodes that can be stored or transmitted. Deserialization works in reverse, taking a data stream and re-building it into an in-memory object or object graph

Serialization and deserialization are mostly used with two objectives:

- Transmit objects across a network or application boundary

- Store representations of objects within a file or database


The three main engines in .NET framework for serialization are the next:

- The data contract serializer

- The binary serializer

- The XML serializer


There is also the IXMLSerializable interface, used to implement own code serialization, using XmlReader and XmlWriter

The data contract serializer is the newest and the most versatile of the three serialization engines and is used by WCF

In this example, we will expose how to use the data contract serializer

There are two ways of using this serializer, through DataContractSerializer class, or through NetDataContractSerializer class. NetDataContractSerializerClass tightly types to data contract types, it relies on the presence of a specific .NET type in a specific namespace and assembly in order to deserialize

If you’re saving an object graph to a “black box", you can choose either serializer, depending on what benefits are more important to you. If you’re communicating through WCF, or reading/writing an XML file, it's highly recommended the DataContractSerializer

This is the class to serialize, and the code to serialize/deserialize

     
	namespace Serialization
    {
        [DataContract]
        public class City
        {
            [DataMember]
            public string Name { get; set; }

            [DataMember]
            public int Cityzens { get; set; }
        }
    }
    

     
	City ciudad = new City() { Name = "Barcelona", Cityzens = 1620940 };

    var ds = new DataContractSerializer(typeof (City));

    // Serialize
    using (Stream stream = File.Create("barcelona.xml"))
        ds.WriteObject(stream, ciudad);
 
    // Deserialize
    City bcn;
    using (Stream stream = File.OpenRead("barcelona.xml"))
        bcn = (City)ds.ReadObject(stream);

    Console.WriteLine("{0}: {1}", bcn.Name, bcn.Cityzens);
    

The result of the previous code is the next


<City xmlns="http://schemas.datacontract.org/2004/07/Serialization" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Cityzens>1620940</Cityzens><Name>Barcelona</Name></City>

DataContractSerializer, and NetDataContractSerializer, both use the XmlFormatter by default, with an XmlWriter, you can request that the xml be intended for readability

     
	City ciudad = new City() { Name = "Barcelona", Cityzens = 1620940 };

    var ds = new DataContractSerializer(typeof (City));

    XmlWriterSettings setts = new XmlWriterSettings() { Indent = true };

    using (XmlWriter writer = XmlWriter.Create("city.xml", setts))
        ds.WriteObject(writer, ciudad);

    System.Diagnostics.Process.Start("city.xml");
    

The result of the previous code is as follows



The XML element name reflects the data contract name, which, by default, is the .NET type name; the XML namespace reflects the data contract namespace, which, by default, is http://schemas.datacontract.org/2004/07/, plus the .NET type namespace. You can override both of them in this way


     
	[DataContract (Name="Ciudad", Namespace="http://innovar.com")]
    public class City
    {
        [DataMember (Name="Nombre")]
        public string Name { get; set; }

        [DataMember (Name="Poblacion")]
        public int Cityzens { get; set; }
    }
    




<METHOD SOFTWARE © 2013>

Friday, May 10, 2013

Profiling LINQ Queries

When we are implementing LINQ queries to retrieve data from our database server, it's a good practice profile the queries through SQL Profiler tool, it might be decisive for improving the query and reducing the time responses

In this example we have our DataContext pointing to a database with a table named B_PRODUCTS, filled with 30000 records for this example

In order to measure the time response of this query into the server side, we will begin a new instance of SQL Profiler tool, and begin a new trace connected to our server



We will make use of the template T-SQL duration, for targeting the duration of the query in milliseconds when is processed by the server. In the events tab of the trace, we can filter the trace log only to those events we want to register



At this point, we run the trace, and launch the query

This is the initial linq query

     
	using (BusinessClassesDataContext context = new BusinessClassesDataContext())
    {
        Products = (from prods in context.B_PRODUCTs
                    orderby prods.Description ascending
                    select prods).ToList<B_PRODUCT>();
    }
    




Now we will include a where clause with 2 conditions and check the trace log

     
		Products = (from prods in context.B_PRODUCTs
                where prods.Description.EndsWith("kit")
                    && prods.IdProduct > 100
                orderby prods.Description ascending
                select prods).ToList<B_PRODUCT>();
                




Now we will change the implementation of the first condition making use of the SqlMethods namespace, the which one includes SQL expressions for querying data

     
		Products = (from prods in context.B_PRODUCTs
                where SqlMethods.Like(prods.Description, "%kit")
                    && prods.IdProduct > 100
                orderby prods.Description ascending
                select prods).ToList<B_PRODUCT>();




With this second approach, we can appreciate a reduction of the time response of 40 milliseconds, with this information we can leverage the most efficient way to query our data


<METHOD SOFTWARE © 2013>

Saturday, May 4, 2013

Solve multiple concurrence with ADO.NET

When we have multiple instances of the same application updating the same database, we have to stablish control for handling the possible concurrence conflicts amidst all requests to the database

In this example we have the next application and data in a grid



The code for submit changes to the database when updated is the next

     
	private void btnUpdate_Click(object sender, EventArgs e)
    {
        commandBuilder = new SqlCommandBuilder(dataAdapterConcerts);
        dataAdapterConcerts.Update(dataSet.Tables["Concerts"]);
        dataSet.AcceptChanges();
    }
    


In order to stablish concurrence control, we are going to implement the event handler RowUpdated of our SqlDataAdapter object

    dataAdapterConcerts.RowUpdated += 
        new SqlRowUpdatedEventHandler(dataAdapter_RowUpdated);


with the next code

     
	private void dataAdapter_RowUpdated(object sender, SqlRowUpdatedEventArgs e)
    {
        if (e.Status == UpdateStatus.ErrorsOccurred)
        {
            solveConcurrence(e.Row);
            e.Status = UpdateStatus.SkipCurrentRow;
        }
    }
    


The method solveConcurrence for the row is as follows

     
private void solveConcurrence(DataRow row)
{
    DataSet actualData = new DataSet();
    dataAdapterConcerts.Fill(actualData, "Concerts");
    dataAdapterHalls.Fill(actualData, "Halls");

    actualData.Tables["Concerts"].PrimaryKey = new DataColumn[] 
        { actualData.Tables["Concerts"].Columns["IdConcert"] };

    DataRow actualRow = actualData.Tables["Concerts"].Rows.Find((int)row["IdConcert"]);

    string message = string.Format("actual value = title: {0} - id hall: {1} - date: {2}
       \r\rproposed value = title: {3} - id hall: {4} - date: {5}",
        actualRow["Title"], actualRow["IdHall"], actualRow["Date"], 
        row["Title"], row["IdHall"], row["Date"]);

    if ((MessageBox.Show("Concurrence conflict\r\rdo you want to override changes?\r\r" 
        + message, "Concerts#",
        MessageBoxButtons.YesNo, MessageBoxIcon.Question)
        == DialogResult.Yes))
    {
        dataSet.Merge(actualData, true);

        dataAdapterConcerts.Update(dataSet.Tables["Concerts"]);

        row.AcceptChanges();
    }
    else
    {
        row["IdConcert"] = actualRow["IdConcert"];
        row["Title"] = actualRow["Title"];
        row["IdHall"] = actualRow["IdHall"];
        row["Date"] = actualRow["Date"];

        row.AcceptChanges();
    }
}


The result of this code when we launch two or more instances of the application and apply different changes on the same row, is the next



Data will be merged or equalized depending on the dialog result


<METHOD SOFTWARE © 2013>

Wednesday, April 24, 2013

Dynamic T-SQL

Dynamic SQL describes any SQL DML statement assembled dynamically at runtime as a string and then submitted

Generate code at runtime is very useful for several tasks:

- Multiple possible query criteria can be dynamically assembled into custom FROM, WHERE, and ORDER BY clauses for flexible queries

- Code can respond to the schema of the database and generate appropriate triggers, CRUD stored procedures, and views

- Dynamic code can auto-generate very consistent stored procedures

In this example we have the next data



and two stored procs which operate on our table CUSTOMERS: the first returns the result set of a SELECT statement with the WHERE clause built dinamically, and the second one updates the indicated field of those records with a certain condition

This is the stored proc for select data

     
	CREATE PROCEDURE SELECT_CUSTOMERS
    (@column_1 VARCHAR(20), @operator_1 VARCHAR(4), @value_1 VARCHAR(50),
     @column_2 VARCHAR(20), @operator_2 VARCHAR(4), @value_2 VARCHAR(50),
     @order_column VARCHAR(20))
AS BEGIN
    
    DECLARE @select_command varchar(2000)

    SET @select_command = 'SELECT FirstName, LastName, Telephone, Email
            FROM C_CUSTOMERS
            WHERE '  + @column_1 + ' ' + @operator_1 +  ' ''' + @value_1 + '' 
            + ''' AND ' + @column_2 + ' ' + @operator_2 + ' ''' + @value_2 + ''''
            + ' ORDER BY ' + @order_column
            
    CREATE TABLE #temp (FirstName VARCHAR(20), LastName VARCHAR(40), 
        Telephone VARCHAR(14), Email VARCHAR(20))

    INSERT INTO #temp EXEC (@select_command)

    SELECT * FROM #temp

    DROP TABLE #temp
    
    RETURN

END
GO


The result of the calling to this proc is the next:

SELECT_CUSTOMERS 'firstname', 'like', 'A%', 'telephone', 'like', '%207%', 'lastname'




This is the stored proc for update data

     
CREATE PROCEDURE UPDATE_CUSTOMERS
   (@column VARCHAR(20), @value VARCHAR(40), @where_clause VARCHAR(200))
AS BEGIN

    DECLARE @update_command varchar(2000)

    SET @update_command = 'UPDATE C_CUSTOMERS SET ' + @column 
        + ' = ''' + @value + ''''
        + 'WHERE ' + @where_clause
    
    EXEC (@update_command)
    
    SELECT CAST(@@ROWCOUNT AS VARCHAR) + ' customers updated' AS Result

END
GO


and the result of the calling is the next:

UPDATE_CUSTOMERS 'email', '----', 'email like ''%test%'''





<METHOD SOFTWARE © 2013>

Sunday, March 24, 2013

XML Type in SQL Server

XML is present in every sort of developments today. Knowingly or unknowingly, every application deals with XML in one way or another. For example, .NET applications use XML files to store configuration information. ASP.NET web pages are XML documents. Almost all modern websites generate and publish information as XML feeds (RDF, RSS, ATOM, OPML, etc.)

In this post we are going to check the XML data type introduced with SQL Server 2005 and improved in SQL Server 2008

The table definition with XML data type is as follows

     
	CREATE TABLE C_EMPLOYEES_PROJECTS
    (
        IdEmployee    INT NOT NULL,
        IdProject   INT NOT NULL,
        ProjectDetails XML,
        
        CONSTRAINT PK_EMP_PROJECTS
            PRIMARY KEY (IdEmployee, IdProject),
        CONSTRAINT FK_EMPLOYEES
            FOREIGN KEY (IdEmployee)
            REFERENCES C_EMPLOYEES(IdEmployee),
        CONSTRAINT FK_PROJECTS
            FOREIGN KEY (IdProject)
            REFERENCES C_PROJECTS(IdProject)
    )
    GO
    


Now we will add a couple of records to the table

     
INSERT INTO C_EMPLOYEES_PROJECTS 
    VALUES (1, 1, 
        '<Project Title="Migration of web application">
            <AssignmentDate>10-10-2012</AssignmentDate>
            <DueDate>04-01-2013</DueDate>
            <Technology>.NET</Technology>
            <CustomerId>4</CustomerId>
        </Project>')

    INSERT INTO C_EMPLOYEES_PROJECTS 
    VALUES (2, 4, 
        '<Project Title="Applets for intranet">
            <AssignmentDate>11-20-2012</AssignmentDate>
            <DueDate>05-01-2013</DueDate>
            <Technology>Java</Technology>
            <CustomerId>3</CustomerId>
        </Project>')   
        


The result of a select statement is the next



XQuery is a language for querying XML data that allows navigational access based on XPath 2.0
The XML data type supports the next methods:

- value(): is useful for extracting scalar values from XML documents as a relational value. This method takes an XQuery expression that identifies a single node and the desired SQL type to be returned

- query(): takes an XQuery expression that evaluates to a list of XML nodes and allows the user to extract fragments of an XML document

- exist(): allows the user to perform checks on XML documents to determine if the result of an XQuery expression is empty or nonempty. The result of this method is 1 if the XQuery expression returns a nonempty result, 0 if the result is empty, and NULL if the XML instance itself is NULL

- modify(): can be used to modify the content of an XML document. It accepts XML DML statements to insert, update, or delete one or more nodes from an XML instance

- nodes(): accepts an XQuery expression and returns a rowset in which each row represents a context node identified by the query expression. Methods of the XML data type such as query(), value(), exist(), and nodes() can also be invoked on the context nodes returned from the nodes() method


Below we present examples of the usage of each method

     
-- Examples of value() 
-- gets the value of the Title attribute of Project node 
SELECT
ProjectDetails.value('/Project[1]/@Title', 'VARCHAR(50)') AS ProjectTitle
FROM C_EMPLOYEES_PROJECTS

-- gets the value of the Title attribute of Project node
SELECT
ProjectDetails.value('(/Project/DueDate)[1]', 'VARCHAR(50)') AS [Due Date]
FROM C_EMPLOYEES_PROJECTS

-- You can also include xquery expressions in WHERE clause
SELECT IdEmployee
FROM C_EMPLOYEES_PROJECTS
WHERE ProjectDetails.value('(/Project/@Title)[1]', 'VARCHAR(50)') LIKE 'Applets%'

SELECT IdEmployee
FROM C_EMPLOYEES_PROJECTS
WHERE ProjectDetails.value('(/Project/Technology)[1]', 'VARCHAR(50)') = '.NET'

--
-- Examples of query()

-- gets the specified xml fragment of the document
SELECT
ProjectDetails.query('/Project/DueDate') AS [Due Date]
FROM C_EMPLOYEES_PROJECTS 

-- gets the text value of the node in the specified xml framgment of the document
SELECT
ProjectDetails.query('/Project/DueDate/text()')  AS [Due Date]
FROM C_EMPLOYEES_PROJECTS 

--
-- Examples of exist()

-- will iterates the Project childnodes and returning 0 / 1 for not exist / exist respectively
SELECT
ProjectDetails.exist('/Project[1]/CustomerId[text() = "4"]')
FROM C_EMPLOYEES_PROJECTS 

--
-- Examples of modify()

-- sets the value of CustomerId node to "2" where idproject = 1
UPDATE C_EMPLOYEES_PROJECTS 
SET ProjectDetails.modify('replace value of (/Project/CustomerId/text())[1] with xs:string("2")')
WHERE IdProject = 1

-- sets the value of Title attribute where idproject = 1
UPDATE C_EMPLOYEES_PROJECTS 
SET ProjectDetails.modify('replace value of (/Project/@Title)[1] with xs:string("Migration of application and database")')
WHERE IdProject = 1

--
-- Example of nodes()

-- gets the value of the AssignmentDate node specified in the xquery expression of nodes function
SELECT P.A.query('text()')
FROM C_EMPLOYEES_PROJECTS
CROSS APPLY ProjectDetails.nodes('/Project/AssignmentDate') as P(A)

-- gets the value of thee Title attribute from the node specified in the xquery expression of nodes function
SELECT P.A.value('@Title', 'VARCHAR(50)')
FROM C_EMPLOYEES_PROJECTS
CROSS APPLY ProjectDetails.nodes('/Project') as P(A)


Finally we will apply a JOIN clause between the value of an xml node with a Relational table

     
SELECT
    EP.ProjectDetails.value('/Project[1]/@Title', 'VARCHAR(50)') 
    AS [Project Title], C.Name
FROM C_EMPLOYEES_PROJECTS EP  
CROSS APPLY ProjectDetails.nodes('/Project/CustomerId') as P(C)
JOIN C_CUSTOMERS C
ON P.C.value('.', 'INT') = C.IdCustomer





<METHOD SOFTWARE © 2013>

Thursday, February 28, 2013

Send and Retrieve Json data

When we develop web applications and we are adding Ajax functionality, it's a best practice using js libraries that implement code for cross-browsing and encapsulate the callings in a clear code way, such as jQuery, instead of using raw Ajax

In this post we have a web site making an async call to the server, the process continues querying a database and returning the response to the client side in json format, so the whole circuit of the process will be the next



The code in the server-side looks like this

     
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static JsonResult getElement(string atomicSymbol)
{
    using (SqlConnection connection = new SqlConnection
    (ConfigurationManager.ConnectionStrings["chemical_bd"].ConnectionString))
    {
        try
        {
            connection.Open();

            SqlCommand proc = new SqlCommand("K_SELECT_ELEMENT", connection);
            proc.CommandType = System.Data.CommandType.StoredProcedure;

            SqlParameter p_ASymbol = new SqlParameter("@asymbol", 
              System.Data.SqlDbType.VarChar, 3);
            p_ASymbol.Value = atomicSymbol;
            p_ASymbol.Direction = System.Data.ParameterDirection.Input;

            SqlParameter p_Name = new SqlParameter("@name",  
              System.Data.SqlDbType.VarChar, 20);
            p_Name.Direction = System.Data.ParameterDirection.Output;

            SqlParameter p_LatinName = new SqlParameter("@latin_name", 
              System.Data.SqlDbType.VarChar, 20);
            p_LatinName.Direction = System.Data.ParameterDirection.Output;

            proc.Parameters.AddRange(new SqlParameter[] { p_ASymbol, p_Name, p_LatinName });

            proc.ExecuteNonQuery();

            Chemical element = new Chemical()
            {
                name = p_Name.Value.ToString(),
                latin_name = p_LatinName.Value.ToString()
            };

            return new JsonResult() { Data = element };
        }
        catch (Exception ex)
        {
            return null;
        }
    }
}

Notice that the method which processes the request is defined as static. The class JsonResponse is defined in System.Web.Mvc namespace

The calling code in the client-side has the next structure

     
function getElement(atomicSymbol) {

    var jsonData = new Object();
    jsonData.atomicSymbol = atomicSymbol;

    var jsonString = JSON.stringify(jsonData);

    $.ajax({
        url: "callprocedure.aspx/getElement",
        type: "POST",
        data: jsonString,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {

            var element = response.d.Data;
            $('#lblResult').text(element.name + " : " + element.latin_name);
        },
        error: function (result) {
            alert('ERROR: ' + result.status + ' ' + result.statusText);
        }
    });   
}

The result with a correct execution is the next




<METHOD SOFTWARE © 2013>

Sunday, February 3, 2013

Add data to Cache

A good use of the cache memory can improve notoriously the deployment of our web applications

While the HTML response associated to a page is stored in cache, the sent requests from this page will not be processed by the server, this implies a considerable reduction of time responses

In order to the server stores the HTML response associated to a page the first time it makes a request we have to apply the OutPutCache directive in our ASP view

     
<%@OutPutCache Duration="30" VaryByParam="*" %>

Where the attribute Duration indicates the time in seconds that the response will be held in cache. Through the attribute VaryByParam we indicate to the server how many kinds of responses should store, if the value is "none", only stores one, with the value "*" stores many different types of responses as different parameter values be added to the url in the request

The class HttpCachePolicy provides the control of cache through code. Every response has an object of type HttpCachePolicy associated, and we can find it in the property Cache of the Response object. Its main properties and methods are the next

- VaryByParams: controls the value of the attribute VaryByParam in the OutPutCache directive

- SetExpires: controls the value of the attribute Duration in the OutPutCache directive

- SetCacheability: this method controls the site where the response will be stored through the enum HttpCacheability, which possible values are the next:
· Private: the response will be cached in the client side, storing a copy of the response in the browser
· Public: The response is cached on both the client and the server and in intermediate proxy servers
· Server: The response is cached only in the server side

The cache memory of the server allows also storing application data in explicit way. The access to cache is key-value pair based

In this example we are adding a float type object to cache stored in the client side for 60 seconds, and reading it in the button's method

     
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Cache.SetCacheability(HttpCacheability.Private);
        this.Cache.Insert("data1", 1234.5F, null, DateTime.Now.AddSeconds(60),
            System.Web.Caching.Cache.NoSlidingExpiration, 
            System.Web.Caching.CacheItemPriority.High, null);
    }

    protected void btnReadCache_Click(object sender, EventArgs e)
    {
        object data = getDataCache("data1");
        if (data != null)
            lblData.Text = data.ToString();
        else
            lblData.Text = "Time expiration exceeded for data1 key";
    }

    private object getDataCache(string key)
    {
        if (this.Cache.Get(key) != null)
            return this.Cache[key];
        else
            return null;
    }
    





<METHOD SOFTWARE © 2013>

Tuesday, January 15, 2013

Encryption of the Connection String

To see the whole process of encriptyon, we will create a new application, will add it a new data source and finally we will encrypt its App.Config section



The created connection string will be stored in the App.config file



     
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <configSections>
        </configSections>
        <connectionStrings>
            <add name="Encryption.Properties.Settings.BUSINESSConnectionString"
                connectionString="Data Source=METHOD-PC;Initial Catalog=BUSINESS;
                Persist Security Info=True;User ID=sa;Password=***"
                providerName="System.Data.SqlClient" />
        </connectionStrings>
    </configuration>


Now we will program a function with the only aim of encrypting the connection strings section

     
    static uint encryptConnectionString()
    {
        try
        {
            Configuration config;
            config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            config.ConnectionStrings.SectionInformation.ProtectSection(null);
            config.Save();

            Console.WriteLine("Encryption Succeeded");
            return 1;
        }
        catch (Exception ex)
        {
            Console.WriteLine("Encryption Error: " + ex.Message);
            return 0;
        }
    }


Now run the program with an administrator account



The encrypted section will still to be readable from the program, but if we open the app.config from any text processor, the result will be the following

     
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <configSections>
        </configSections>
        <connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
            <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
                xmlns="http://www.w3.org/2001/04/xmlenc#">
                <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
                <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                    <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
                        <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
                        <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                            <KeyName>Rsa Key</KeyName>
                        </KeyInfo>
                        <CipherData>
                            <CipherValue>UXZP4hcmgnrleCwGuRzpigvJ</CipherValue>
                        </CipherData>
                    </EncryptedKey>
                </KeyInfo>
                <CipherData>
                    <CipherValue>uG2JUaE+Rq3ggcx5oUxJtGWwwAZcxo6SwS96Ro2Pgz1/U5</CipherValue>
                </CipherData>
            </EncryptedData>
        </connectionStrings>
    </configuration>
    


The encryption algorithm used in this example is RSA (Rivest, Shamir, and Adleman) a public key cryptography system developed in 1977. It is the first and most widely used algorithm of this type and it is valid to both encrypt and digitally sign

<METHOD SOFTWARE © 2013>