Posts

....
Technical Blog for .NET Developers ©

Saturday, October 14, 2017

MVC4 Multi-language

Application Resources can be created in ASP.NET applications with two different scopes, depending on the level you want to share these resources across the application

In this example we will create a set of global resources containing dictionaries for the application display in three different languages: English (en), Spanish (es), and Catalán (ca)



The application we will build is a data-entry form based on Guest model, and will be displayed in the selected language


    public class Guest
    {
        [Required(ErrorMessageResourceType = typeof(Resources.Dictionary), 
         ErrorMessageResourceName="RequiredFirstName")]
        public string FirstName { get; set; }

        [Required(ErrorMessageResourceType = typeof(Resources.Dictionary), 
         ErrorMessageResourceName = "RequiredLastName")]
        public string LastName { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:d}")]
        public DateTime? BirthDate { get; set; }
    }




We will add the next div element to the _layout.cshtml view in order to generate the language selector


    <div class="content-wrapper">
        @{
            CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
            string selectedLanguageStyle = "background-color:#FFDAA3;font-weight:bold;";
            <div class="float-right">                        
            @switch (currentCulture.TwoLetterISOLanguageName)
            {
                case "en":
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "en-US" })'>English</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "es-ES" })'>Spanish</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "ca-ES" })'>Catalán</a>
                    break;
                case "es":
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "en-US" })'>English</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "es-ES" })'>Spanish</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "ca-ES" })'>Catalán</a>
                    break;
                case "ca":
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "en-US" })'>English</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "es-ES" })'>Spanish</a>
                    <a href='@Url.Action("ChangeLanguage", 
                                            "Home", new { culture = "ca-ES" })'>Catalán</a>
                    break;
            }
            </div>
        }
    </div>


This is the action method called from the language selectors (anchor elements), inside the HomeController


    public ActionResult ChangeLanguage(string culture)
    {
        Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
        Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture;

        Session["lang"] = culture;

        return Redirect(Request.UrlReferrer.ToString());
    }


The approach is this: we will create a BaseController to handle the ExecuteCore method, and stablish the thread's current culture. ExecuteCore method invokes the action in the current controller context. The controllers in our application will inherit BaseController


    public class BaseController : Controller
    {
        //
        // GET: /Base/

        protected override void ExecuteCore()
        {
            var culture = Session["lang"] ?? "en-US";        

            Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture.ToString());
            Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture;

            base.ExecuteCore();
        }

        protected override bool DisableAsyncSupport
        {
            get { return true; }
        }
    }


DysableAsyncSupport property gets whether to disable the asynchronous support for the controller. This flag is for backwards compatibility. ASP.NET MVC 4. allows a controller to support asynchronous patterns. This means ExecuteCore doesn't get called on derived classes. Derived classes can override this flag and set to true if they still need ExecuteCore to be called

The strongly-typed view based on Guest model is this:


@model MvcApp1.Models.Guest

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>@Resources.Dictionary.ViewTitle</h2>

<div>
    @using (Html.BeginForm())
    {
        @Html.ValidationSummary(true)
        <table>
            <tbody>
                <tr>
                    <td>
                        <div class="editor-field">
                            <span>@Resources.Dictionary.FirstName</span>
                        </div>                        
                    </td>
                    <td>
                        @Html.EditorFor(model => model.FirstName)
                        @Html.ValidationMessageFor(model => model.FirstName)                        
                    </td>
                </tr>
                <tr>
                    <td>
                        <div class="editor-field">
                            <span>@Resources.Dictionary.LastName</span>
                        </div>                        
                    </td>
                    <td>
                        @Html.EditorFor(model => model.LastName)
                        @Html.ValidationMessageFor(model => model.LastName)                        
                    </td>
                </tr>
                <tr>
                    <td>
                        <div class="editor-field">
                            <span>@Resources.Dictionary.BirthDate</span>
                        </div>                        
                    </td>
                    <td>
                        @Html.EditorFor(model => model.BirthDate)
                    </td>
                </tr>
            </tbody>
        </table>
        <input type="submit" value="Save"/>
    }    
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}


The result is the next:




<METHOD SOFTWARE © 2014>

Tuesday, May 9, 2017

Generics : Ordered Collections

Ordered Collections are correspondants collections of IEnumerable and IQueryable types

As we apply order by clauses the collections become IOrdered_

In this post we have a simple demo, intended to create a third ordered collection using the implementation of the method CreateOrderedEnumerable







Now we are creating a IOrderedQueryable collection from the first one, in its implementation of enumerable is the function of the queryable expression



Saturday, January 28, 2017

Json RPC Requests

Json RPC is becoming an extended messaging system as it is adjusted to most of actual web scenarios

Nugets for json de-serialization implement the structures to parametrize the request, we are adding Newtonsoft libraries



The method to invoke is in server side gurujsonrpc.appsoft.com, requires id and one param, and its response is a json structure with version, id, and result

The request class exposes one method returning the raw WebResponse of the invocation


    public class JsonRPCClient : HttpWebClientProtocol
    {
        public string MethodVerb { get; set; }

        public string Version { get; set; }

        public string Id { get; set; }

        public string InvokeUrl { get; set; }

        public string MethodName { get; set; }

        public object ParamsElements { get; set; }


        public WebResponse Invoke()
        {
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(InvokeUrl);

            webRequest.ContentType = "application/json-rpc";
            webRequest.Method = MethodVerb;

            JObject message = new JObject();
            message.Add(new JProperty("jsonrpc", Version));
            message.Add(new JProperty("id", Id));
            message.Add(new JProperty("method", MethodName));

            if (ParamsElements != null)
            {
                object[] _params = new [] { ParamsElements };

                JArray _elements = new JArray();
                _elements.Add(_params);

                message.Add(new JProperty("params", _elements));
            }

            string s = JsonConvert.SerializeObject(message);
            byte[] byteArray = Encoding.UTF8.GetBytes(s);
            webRequest.ContentLength = byteArray.Length;
            Stream dataStream = webRequest.GetRequestStream();
            dataStream.Write(byteArray, 0, byteArray.Length);
            dataStream.Close();

            WebResponse webResponse = webRequest.GetResponse();

            return webResponse;
        }

    }


The method response returns the json object with the results


            var client = new JsonRPCClient
                {
                    InvokeUrl = "https://gurujsonrpc.appspot.com/guru",
                    MethodName = "guru.test",
                    MethodVerb = "POST",
                    Version = "2.0",
                    Id = "123",
                    ParamsElements = "Guru"
                };

            var response = client.Invoke();

            Stream responseStream = response.GetResponseStream();

            StreamReader reader = new StreamReader(responseStream);

            string result = reader.ReadToEnd();





Saturday, January 21, 2017

F# : Recursive loops

Recursive functions is one of key concepts of functional programming. F# prefix these functions with keyword rec

In this sample we have defined three functions, two of them recursives, and one of them returning a type int list. The result is the factorization of the number in parameter

Algorithm gets a lot simplified by step in the logic of factorization. This is the algorithm translated to F#



        let divide x s = (x % s) = 0

        let rec lowFactor x s = if (divide x s) then s else lowFactor x (s + 1)

        let rec factorize x =
            [
                if (x <> 1) then

                    let i = lowFactor x 2

                    yield i

                    if (divide x i) then

                        for k in factorize (x / i) do

                            yield k

            ]

        let tst = factorize 108416 


<METHOD SOFTWARE 2020 ©>

Monday, January 2, 2017

MVC4 Ajax Forms

ASP.NET MVC 4 includes Ajax functionalities based on jQuery javascript library. Most of the Ajax features in the framework build on or extend features in jQuery

In this post we will implement an asynchronous request form with validation

This is the Chemical model in our Application

 
    public class ChemicalElement
    {
        public int IdElement { get; set; }

        [DisplayName("Name")]
        [Required]
        public string Name { get; set; }

        [DisplayName("Latin name")]
        [Required]
        public string LatinName { get; set; }

        [DisplayName("Symbol")]
        [Required]
        [RegularExpression(@"\b[a-zA-Z]{1,3}\b")]
        public string Symbol { get; set; }
    }
        


We have imported the next SQL schema (table and stored procedure)



The code to release the search of chemical elements is the next


    public PartialViewResult SearchChemicalElements(string search)
    {
        var elementsModel = SearchElementsModel(search);

        return PartialView("Elements", elementsModel);
    }

    private IEnumerable<ChemicalElement> SearchElementsModel(string search)
    {
        var allElements = Elements.SearchElements(search);

        return allElements;
    }
        


And in the Elements class the implementation of the SearchElement method is this

   
	public static IEnumerable<ChemicalElement> SearchElements(string search)
    {
        using (CHEMICALSEntities context = new CHEMICALSEntities())
        {
            ObjectResult<SearchElementsBySymbol_Result> matchElements =
                context.SearchElementsBySymbol("%" + search + "%");

            foreach (var element in matchElements)
                yield return new ChemicalElement()
                {
                    IdElement = element.IdElement,
                    Name = element.Name,
                    LatinName = element.LatinName,
                    Symbol = element.Symbol
                };
        }
    }
        


The code in the View to make the process work asynchronously, is the next


@using (Ajax.BeginForm("SearchChemicalElements", "Chemical", new AjaxOptions
    {
        InsertionMode = InsertionMode.Replace,
        HttpMethod = "GET",
        LoadingElementId = "preloader",
        UpdateTargetId = "searchResults",
    }))
        


This code renders an html form with the next marks



The information about how to perform the AJAX request is contained in the DOM, and it is released by the jquery.unobtrusive-ajax.js code

The PartialView for Elements is strongly typed and renders a table in a loop for each element



The validation rules are specified in the model, so the code in the view

 
@Html.TextBoxFor(m => m.Symbol, new { Name = "search"})


will renders the information into these data dash attributes


data-val="true" 
data-val-regex="The field Symbol must match the regular expression '\b[a-zA-Z]{1,3}\b'." 
data-val-regex-pattern="\b[a-zA-Z]{1,3}\b" 
data-val-required="The field Symbol is required." 
id="Symbol" name="search"
    


The Ajax request, and validation are implemented inside the jQuery scripts

  
  @section scripts {
    <script type="text/javascript" src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
    <script type="text/javascript" src="~/Scripts/jquery.validate.min.js"></script>
    <script type="text/javascript" src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
}    


Thursday, April 28, 2016

Dynamic Types: Indexers

When we are using Indexers in order to access our variables, we can expand the property through a dynamic reference of the accessed variable, we achieve this through ExpandoObject of System.Dynamic namespace

In this example we set values in a Dictionary type variable, and expand the property name on a dynamic variable


            dynamic Values = new ExpandoObject();

            var _Values = Values as IDictionary<string, object>;

            _Values["Name"] = "Little Writer";
            _Values["Weight"] = 1550.0M;

            string name = Values.Name;
            decimal weight = Values.Weight;


Thursday, February 4, 2016

HTML5 API Indexed Database

API Indexed Database is the officially supported by W3C way for the creation of databases with HTML5

This system takes the concept of key/value pairs to store data. the Database can contain Stores, the equivalent to the SQL tables, and each Object Store contains key/value pairs; this API is not a relational database, but object oriented. you can query this database inline as offline

The first step in this example will be creating a new database, for this we use the open() method, the syntax is as follows:
 
    indexedDB.open("database_name", version)    
    
    
If the database does not exist, it is created, else, it is open. The call to the open() function returns an IDBOpenDBRequest object with a result (success) or error value that you handle as an event

In this example we build the next web form, and implement a Web Method in the server side which returns an array of json objects for loading the database



The js code to open the database and create the object store is the next


    var HTML5DB = {};
    HTML5DB.indexedDB = {};
    HTML5DB.indexedDB.db = null;

    window.indexedDB = window.indexedDB || window.mozIndexedDB || 
                       window.webkitIndexedDB || window.msIndexedDB;
    window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || 
                            window.msIDBTransaction;
    window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || 
                         window.msIDBKeyRange;

    HTML5DB.indexedDB.onerror = function (e) { console.log(e); };

    HTML5DB.indexedDB.open = function () {

        var version = 1;
        var request = window.indexedDB.open("db_example", version);

        request.onupgradeneeded = function (e) {

            var db = e.target.result;
            e.target.transaction.onerror = HTML5DB.indexedDB.onerror;
            var store = db.createObjectStore("object_store", 
                { keyPath: "id", autoIncrement: true });
        };

        request.onsuccess = function (e) {
            HTML5DB.indexedDB.db = e.target.result;
            HTML5DB.indexedDB.getAllRecords();
        };

        request.onerror = HTML5DB.indexedDB.onerror;
    };
        


The code to add and delete records is the next:

Since the id has been declared autoIncrement, we are inserting a record initializing two fields in the value property (value, and timeStamp)


    HTML5DB.indexedDB.addRecord = function (value) {

        var db = HTML5DB.indexedDB.db;
        var trans = db.transaction(["object_store"], "readwrite");
        var store = trans.objectStore("object_store");

        var data = {
            "value": value,
            "timeStamp": new Date($.now()).toLocaleTimeString()
        };

        var request = store.put(data);

        request.onsuccess = function (e) {
            HTML5DB.indexedDB.getAllRecords();
        };

        request.onerror = function (e) {
            console.log("Error Adding: ", e);
        };
    };

    HTML5DB.indexedDB.deleteRecord = function(id) {
      var db = HTML5DB.indexedDB.db;
      var trans = db.transaction(["object_store"], "readwrite");
      var store = trans.objectStore("object_store");

      var request = store.delete(id);

      request.onsuccess = function(e) {
        HTML5DB.indexedDB.getAllRecords();
      };

      request.onerror = function(e) {
        console.log("Error deleting: ", e);
      };
    };
        


The next is the code to retrieve and render records from the database:


    HTML5DB.indexedDB.getAllRecords = function() {

      $('#dbRecords tr').remove();

      var db = HTML5DB.indexedDB.db;
      var trans = db.transaction(["object_store"], "readwrite");
      var store = trans.objectStore("object_store");

      var keyRange = IDBKeyRange.lowerBound(0);
      var cursorRequest = store.openCursor(keyRange);

      cursorRequest.onsuccess = function(e) {
        var result = e.target.result;
        if(!!result == false)
          return;

        renderRecord(result.value);
        result.continue();
      };

      cursorRequest.onerror = HTML5DB.indexedDB.onerror;
    };

    function renderRecord(record) {

        $("#dbRecords").find('tbody')
            .append($('<tr>')
                .append($('<td>')
                    .append($('<span>')
                        .html(record.value)
                    )
                )
                .append($('<td>')
                    .append($('<span>')
                        .html(record.timeStamp)
                    )
                )
                .append($('<td>')
                    .append($('<a>')
                        .attr('href', 
                              'javascript:HTML5DB.indexedDB.deleteRecord(' + record.id + ')')
                        .html('Delete')
                )
            ));
    }
        


Here is the result of this code in the client side:



Finally we have implemented this call to the server to retrieve a collection of json objects and preload the database:

 
    function getData() {

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

                var records = json.d.Data.records;

                for (var i = 0; i < records.length; i++) {

                    HTML5DB.indexedDB.addRecord(records[i].Data.value);
                }
            },
            error: function (e) {
                alert('ERROR: ' + e.status + ' : ' + e.statusText);
            }
        });
    }
        


    
    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public static JsonResult getData()
    {
        List<JsonResult> recordSet = new List<JsonResult>();

        for (int i = 0; i < 10; i++)
        {
            Record rec = new Record();
            rec.value = "record " + i.ToString();
            recordSet.Add(new JsonResult() { Data = rec });
        }

        JsonResult result = new JsonResult();
        result.Data = new Result() { records = recordSet };
        return result;
    }

    private class Result
    {
        public List<JsonResult> records;
    }

    private class Record
    {
        public string value;
    }
        





<METHOD SOFTWARE © 2014>

Sunday, January 24, 2016

Windows Services

Windows Services are applications that run in the background, performing diverse tasks and designed not to require user intervention

In this example, we are going to deploy a Windows Service which detects changes on a .txt file and will take its data to a database

The first step is begin a Windows Service Project



The code template of the Windows Service is as follows


namespace WSWatcher
{
    public partial class Service1 : ServiceBase
    {
        public SWatcher()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
        }

        protected override void OnStop()
        {
        }
    }
}
    


Now we add a .config file with the path of the archive to watch, and the connection string to the database

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="file_path" value="C:\ExampleData" />
  </appSettings>
  <connectionStrings>
    <add name="conSet" providerName="System.Data.SqlClient" 
         connectionString="Data Source=***; Initial Catalog=PRODUCTS; User=***; Pwd=***"/>
  </connectionStrings>
</configuration>


We add the FileSystemWatcher class to our code, and implement handlers for Created and Changed Events


protected override void OnStart(string[] args)
{
    fileWatcher = new FileSystemWatcher(ConfigurationManager.AppSettings["file_path"]);
    fileWatcher.Filter = "*.txt";
    fileWatcher.EnableRaisingEvents = true;
    fileWatcher.Changed += new FileSystemEventHandler(fileWatcher_Changed);
    fileWatcher.Created += new FileSystemEventHandler(fileWatcher_Created);
}

void fileWatcher_Created(object sender, FileSystemEventArgs e)
{
    bulkData(e.ChangeType);
}

void fileWatcher_Changed(object sender, FileSystemEventArgs e)
{
    bulkData(e.ChangeType);
}

void bulkData(WatcherChangeTypes changeType)
{
    string[] lines = System.IO.File.ReadAllLines(fileWatcher.Path + "\\data.txt");

    using (SqlConnection connection = 
    new SqlConnection(ConfigurationManager.ConnectionStrings["conSet"].ConnectionString))
    {
        connection.Open();
        foreach (string line in lines)
        {
            SqlCommand comm = connection.CreateCommand();
            comm.CommandType = CommandType.StoredProcedure;
            comm.CommandText = changeType == WatcherChangeTypes.Created
                ? "INSERT_PRODUCT"
                : "UPDATE_PRODUCT";
            comm.Parameters.Add(new SqlParameter("@idproduct", 
                Convert.ToInt32(line.Split('-')[0])));
            comm.Parameters.Add(new SqlParameter("@pname", line.Split('-')[1]));
            comm.ExecuteNonQuery();
        }
    }
}
    


It's time to create the installer for the service, right click on the service designer and add a new installer



Select serviceInstaller1 on the designer, and make sure the ServiceName property is set to SWatcher

Now click serviceProcessInstaller1 and set the Account property to LocalSystem. This will cause the service to be installed and to run on a local service account.

To build your project, before set the Startup object to point to your service. In Project Properties, on the Application page, from the Startup object list, click SWatcher.Program



Now build the solution, run Developer Command Prompt as Administrator, navigate to your bin folder, and type the command for installing the service

installutil.exe SWatcher.exe




Check the Service in the Control Panel, with the configuration specified in development, LocalSystem Account

Now we test the service, creating a file with the next data



The result is immediately appreciated

A change in the file will produces the next result



<METHOD SOFTWARE © 2012>

Friday, December 26, 2014

Extension Methods

Extension methods are static methods, in static classes, marked up to be added to existing types without creating a new derived type, or modifying the original type. You can use extension methods to extend a class or interface. This feature was introduced in C# 3.0

In this example we will implement extension methods for two different data types: DateTime, and IEnumerable

This is the implementation of the methods in this example

 
    public static class ExtensionMethods
    {
        public static string ToLetterFormat(this DateTime dateTime)
        {
            return dateTime.ToString("MMMM d',' yyyy");
        }

        public static IEnumerable<string> GetOnlyStrings<T>(this IEnumerable<T> list)
        {
            foreach (var item in list)
            {
                if (item is string)
                    yield return item as string;
            }
        }
    }
        


The markup that makes these extension methods is the keyword this used before the first parameter in the parameter list of the method. This keyword is specific to C#, and it instructs the compiler to add the ExtensionMethodAttribute to the method

The first method produces a result like this:

  
    string letterFormatDate = (DateTime.Today).ToLetterFormat();

    Console.WriteLine(letterFormatDate);
    Console.ReadKey();
        




The second method produces this result:


 
    customList.ForEach(l => Console.WriteLine(l.GetType().ToString()));
    Console.ReadKey();

    List<string> allStringsFromCustomList = customList.GetOnlyStrings().ToList();

    Console.WriteLine(Environment.NewLine);

    allStringsFromCustomList.ForEach(s => Console.WriteLine(s));

    Console.ReadKey();
        





<METHOD SOFTWARE © 2014>

Sunday, September 14, 2014

Entity Framework Change Tracker

With ChangeTracker we can track the state of the entities in the database context, so when our processes work into a context we can work on specific group of entities

In this example we have this diagram and a class which handles the retrieve and insert methods. This is the implementation:



 
        public IEnumerable<GALAXIES> GetKnownGalaxies()
        {
            return (from GALAXIES galaxies in _context.GALAXIES select galaxies);
        }

        public void InsertGalaxy(GALAXIES galaxy)
        {
            _context.GALAXIES.Attach(galaxy);
            _context.Entry(galaxy).State = EntityState.Added;
            _context.GALAXIES.Add(galaxy);
        }
       


Now we add a third method to retrieve only the added galaxies:

     
        public IEnumerable<GALAXIES> GetNewGalaxies()
        {
            return
                (from GALAXIES galaxies in _context.ChangeTracker.Entries()
                     .Where(e => e is GALAXIES && e.State == EntityState.Added)
                     .Select(e => e.Entity as GALAXIES)
                 select galaxies);
        }

        public void InsertNewGalaxy()
        {
            GALAXIES newGalaxy = new GALAXIES()
                {
                    Name = "Cartwheel Galaxy",
                    Distance = (decimal)1.5,
                    Magnitude = (decimal)2.9
                };

            galaxyClass.InsertGalaxy(newGalaxy);
        }
    


The result of the program with this sequence is the next:

     
        var knownGalaxies = galaxyClass.GetKnownGalaxies().ToList();

        knownGalaxies.ForEach(
            x =>
            Console.WriteLine("{0}: {1} distance, {2} magnitude", 
                                x.Name, x.Distance.ToString(),
                                x.Magnitude.ToString()));

        Console.WriteLine(Environment.NewLine);
        Console.ReadKey();

        InsertNewGalaxy();

        var newGalaxies = galaxyClass.GetNewGalaxies().ToList();

        newGalaxies.ForEach(
            x =>
            Console.WriteLine("{0}: {1} distance, {2} magnitude", 
                                x.Name, x.Distance.ToString(),
                                x.Magnitude.ToString()));
    





<METHOD SOFTWARE © 2014>

Sunday, April 20, 2014

LINQ Compiled Queries

The process of converting LINQ queries to SQL statements, involves syntax check, and the construction of the SQL query, this task is performed every time we launch the LINQ query

In compiled queries, the syntax check and construction plan are cached in a static class, so LINQ uses this cached plan from the static class object instead of re-building it in sequent executions

In this example we have the next diagram of LINQ to SQL Classes



We will compile these two queries. A compiled query is stored in a Func delegate, where the first argument must be an instance of DataContext (or derived), and the last argument must be the type returned from the query, you can define up to three arguments in the middle as parameters of the compiled query. You will need to specify these arguments for each compiled query invocation

 
        private static Func<BusinessClassesDataContext, DateTime, IQueryable<B_SALES>>
            SalesByDate = CompiledQuery.Compile(
                (BusinessClassesDataContext ctx, DateTime saleDate) =>
                    (from sl in ctx.GetTable<B_SALES>()
                     where sl.SALEDATE >= saleDate
                     select sl));

        private static Func<BusinessClassesDataContext, int, Decimal>
            SalesAverageByCustomer = CompiledQuery.Compile(
                (BusinessClassesDataContext ctx, int idCustomer) =>
                    (from sl in ctx.B_SALES
                     where sl.B_CUSTOMERS.IdCustomer == idCustomer
                     group sl by sl.Price
                     into sales
                     select sales.Average(sl => sl.Price)).First());
                         


Now the code calling these queries is the next

 
        using (BusinessClassesDataContext context = new BusinessClassesDataContext())
        {
            foreach (B_SALES sale in SalesByDate(context, saleDate))
            {
                Console.WriteLine("{0} : {1}", sale.IdSale, sale.IdProduct);
            }

            Console.WriteLine("{0:N2}$", SalesAverageByCustomer(context, 1));
        }            
    



<METHOD SOFTWARE © 2014>

Sunday, February 2, 2014

LINQ Group Operations

In this post we will make a review of the main grouping operations applied with LINQ

The first step will be adding our diagram of LINQ to SQL Classes



For the sake of simplicity, we will program the function LoadContext, which we will call once and will preload data in typed lists

  
    static void LoadContext()
    {
        using (BusinessDataContext businessCtx = new BusinessDataContext())
        {
            customers = (from cst in businessCtx.B_CUSTOMERs
                            select cst).ToList<B_CUSTOMER>();

            products = (from prd in businessCtx.B_PRODUCTs
                        select prd).ToList<B_PRODUCT>();

            providers = (from prv in businessCtx.B_PROVIDERs
                            select prv).ToList<B_PROVIDER>();

            providers_products = (from prv_prd in businessCtx.B_PROVIDERS_PRODUCTs
                                    select prv_prd).ToList<B_PROVIDERS_PRODUCT>();

            sales = (from sls in businessCtx.B_SALEs
                        select sls).ToList<B_SALE>();
        }
    }
        


The next method will make an average of sales grouped by customers, and grouped by products in the second case

  
    static void getAvgSales()
    {
        var avgSalesByCustomer = 
            (from s in sales
                join c in customers
                on s.IdCustomer equals c.IdCustomer
                group s by new { c.FirstName, c.LastName } into cust
                orderby cust.Key.FirstName
                select new
                {
                    Customer = cust.Key.FirstName + " " + cust.Key.LastName,
                    CountSales = cust.Count(),
                    AvgSales = cust.Average(sl => sl.Price)
                });


        var avgSalesByProduct = 
            (from s in sales
                join p in products
                on s.IdProduct equals p.IdProduct
                group s by new { p.Description } into product
                orderby product.Key.Description
                select new
                {
                    Product = product.Key.Description,
                    CountSales = product.Count(),         
                    CountUnits = product.Sum(sl => sl.Cuantity),
                    AvgSales = product.Average(sl => sl.Price)
                });
            
        Console.WriteLine("\n\nAVERAGE BY CUSTOMER\n\n");
        foreach (var avgSale in avgSalesByCustomer)
            Console.WriteLine("{0} : {1} purchases : {2}$", avgSale.Customer, 
                avgSale.CountSales, string.Format("{0:N2}", avgSale.AvgSales));

        Console.WriteLine("\n\nAVERAGE BY PRODUCT\n\n");
        foreach (var avgSale in avgSalesByProduct)
            Console.WriteLine("{0} : {1} sales : {2} units : {3}$", avgSale.Product, 
                avgSale.CountSales, avgSale.CountUnits, string.Format("{0:N2}", 
                avgSale.AvgSales));
    }
        


The output is as follows



The next method will extract sales data grouped by product and the different periods of sale date
  
    static void getSalesByDate()
    {
        var salesByPeriod = 
            (from s in sales
                group s by new 
                { s.B_PRODUCT.Description, s.SaleDate} into grp
                orderby grp.Key.SaleDate, grp.Key.Description
                select new
                {
                    Date = grp.Key.SaleDate.Value.ToString("MM/yyyy"),
                    Product = grp.Key.Description,
                    CountSales = grp.Count(),
                    CountUnits = grp.Sum(sl => sl.Cuantity),
                    AvgSales = grp.Average(sl => sl.Price)
                });

        Console.WriteLine("\n\nAVERAGE BY DATE PERIOD\n\n");
        foreach (string date in salesByPeriod.Select(s => s.Date).Distinct())
        {
            Console.WriteLine(date);
            foreach (var sale in salesByPeriod.Where(s => s.Date == date))
                Console.WriteLine("-- {0} : {1} sales : {2} units : {3}$",
                    sale.Product, sale.CountSales, sale.CountUnits, 
                    string.Format("{0:N2}", sale.AvgSales));
        }
    }
        


Notice that in this occasion, we don't have performed the join to the product set, instead, we have used the access property to the set of products from the set of sales
The result is the next



We can also use lambda syntax in order to release more group operations, such as max or min

  
    static void getSalesByDate()
    {
        var salesByPeriod = 
            (from s in sales
                group s by new 
                { s.B_PRODUCT.Description, s.SaleDate} into grp
                orderby grp.Key.SaleDate, grp.Key.Description
                select new
                {
                    Date = grp.Key.SaleDate.Value.ToString("MM/yyyy"),
                    Product = grp.Key.Description,
                    CountSales = grp.Count(),
                    CountUnits = grp.Sum(sl => sl.Cuantity),
                    AvgSales = grp.Average(sl => sl.Price)
                });


        var maxSalesDate = (from sl in salesByPeriod select sl)
            .Where(sl => sl.AvgSales == salesByPeriod.Max(sld => sld.AvgSales));

        Console.WriteLine(maxSalesDate.First());
    }
        


The result is this




<METHOD SOFTWARE © 2014>

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>