Monday, 24 April 2017

Printing PDFs on network printer through c# from application hosted in IIS

Printing on network printers or even in local printers programmatically is always a challenge because of the network printer accessibility through code.

I had a requirement where I need to print pdf on network printer programmatically. I found couple of major issues which is a common issue faced by many people but never got satisfactory or final solution over the internet search. It took couple of days to solve the issues and get the final working solution.

Here are the issues which I faced:
Issue #1: Loading the pdf and sending it to the printer.
During the work I got an article which is well explained about the problem of reading pdf and it has couple of alternative solutions provided but this wasn't a satisfactory solution as our client has do the another software installation as pdf reader.
http://www.bincsoft.com/blog/background-printing-of-pdf-documents/

Here I found PdfiumViewer which is an open source provided under Apache licence which helps to read/modify the pdfs programmatically and client/server doesn't need to have anything new installation.

And here is the code to read the pdf and send it to the printer:


public void SendPdfToPrinter(string filePath, string fileName, string printerNetworkPath)
        {
            // Create the printer settings for our printer
            var printerSettings = new System.Drawing.Printing.PrinterSettings
            {
                PrinterName = printerNetworkPath,
                PrintFileName = fileName,
                PrintRange = System.Drawing.Printing.PrintRange.AllPages,
            };
            printerSettings.DefaultPageSettings.Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0);

            // Now print the PDF document
            using (var document = PdfiumViewer.PdfDocument.Load(filePath))
            {
                using (var printDocument = document.CreatePrintDocument())
                {
                    printDocument.DocumentName = fileName;
                    printDocument.PrinterSettings = printerSettings;
                    printDocument.PrintController = new System.Drawing.Printing.StandardPrintController();
                    printDocument.Print();
                }
            }
        }




Here PdfiumViewer.PdfDocument.Load() provides overloaded method to create a pdfdocument from Stream as well.

Issue #2: Printer accessibility issue.
if your application's application pool identity uses any of the built-in accounts (i.e. LocalSystem, LocalService etc) then you will face a issue of accessing the printer. Because your printers doesn't support these users.
There are two possible solutions to overcome this problem:
  • Set Application Pool identity to a custom user (domain user) which has accessibility to the printers.
  • Use impersonation to impersonate a user and print. below is the code to achieve the impersonation.

    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    public class Impersonation : IDisposable
    {
        private readonly SafeTokenHandle _handle;
        private readonly WindowsImpersonationContext _context;
        bool disposed = false;

        const int LOGON32_PROVIDER_DEFAULT = 0;
        const int LOGON32_LOGON_INTERACTIVE = 2;

        public Impersonation(ImpersonateUserDetails user) : this(user.Domain, user.UserName, user.Password)
        { }
        public Impersonation(string domain, string username, string password)
        {
            var ok = LogonUser(username, domain, password,
                           LOGON32_LOGON_INTERACTIVE, 0, out this._handle);
            if (!ok)
            {
                var errorCode = Marshal.GetLastWin32Error();
                throw new ApplicationException(string.Format("Could not impersonate the elevated user.  LogonUser returned error code {0}.", errorCode));
            }

            this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
                return;

            if (disposing)
            {
                this._context.Dispose();
                this._handle.Dispose();
            }           
            disposed = true;
        }

        ~Impersonation()
        {
            Dispose(false);
        }


        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
        {
            private SafeTokenHandle()
                : base(true) { }

            [DllImport("kernel32.dll")]
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            [SuppressUnmanagedCodeSecurity]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool CloseHandle(IntPtr handle);

            protected override bool ReleaseHandle()
            {
                return CloseHandle(handle);
            }
        }
    }

    public class ImpersonateUserDetails
    {
        public string UserName { get; set; }

        public string Password { get; set; }

        public string Domain { get; set; }
    }

One big catch here is that, you must have to use "LOGON32_LOGON_INTERACTIVE" as a "dwLogonType" param value while calling "LogonUser()" method. if you use something else (like LOGON32_LOGON_NEW_CREDENTIALS = 9) you will not get any error but printing won't work. Code will send the document to print queue with owner name as your machine name, file name as printdocument and size as 0 bytes. Overall impersonation is unsuccessful hence printing will fail.




using (new Impersonation("domain", "username", "password"))
{
    string filePath = @"c:\temp\printfile.pdf";
    string fileName = "printfile.pdf";
    \\this should be the fully qualified name of the printer.
    string printerName = @"\\server_name\printer_name"; 
    SendPdfToPrinter(content, docName, printerFullName);
}

Issue #3: Impersonation issue for 32 bit application.
In case if your application is hosted as 32 bit application then you will receive an Win32Exception saying “The handle is not valid." for impersonating the user.This is a well known issue of Microsoft for impersonation and they have patches releases for that as well. For more information refer this:
Printing successfully using impersonation from a 32-bit application-on-a-64-bit-system/

And if your application is using 64-bit application setup then no problem, you are ready to go.


Wednesday, 14 September 2016

Upload/Download large file through WCF REST Service streaming

Hello Frnds,

There was a requirement related to this and before I started working on this I thought everything would be simple and straight forward. But When I finished with the coding as per my thought, I had a problem regarding uploading a big file (>1 GB) and downloading the file and the problem was:
Problem #1: Getting
Problem #2: File was getting downloaded but browser was not able to open the file in specific file format because he din't have the information about "what type of file it is? (file mimetype)".
It took a little while to solve this problem for me and the fix was very simple. All I had to do is to return the file type (mimetype info) as part of response header and here was the trick, and I thought it could be good information to share with you all.
So Let's do it.

I'll start with WCF REST service definition and this is how it should be:

 [ServiceContract]  
   public interface IFileHandlerService  
   {  
     [OperationContract]  
     [XmlSerializerFormat]  
     [Description("Get the template for window")]  
     [WebInvoke(Method = "POST", UriTemplate = "file?fileName={fileName}")]  
     void UploadFile(string fileName, Stream fileContent);  

     [OperationContract]  
     [XmlSerializerFormat]  
     [Description("Get the template for window")]  
     [WebInvoke(Method = "GET", UriTemplate = "file?fileName={fileName}")]  
     Stream DownloadFile(string fileName);  
   }  

and the here is implementation for above service definition:


public class FileHandlerService : BaseFileHandlerService, IFileHandlerService
    {
        public Stream DownloadFile(string fileName)
        {
            Stream fileStream = GetFileStream(fileName); //Here I am getting the actual file as a stream. You could get the file stream from
            //many sources like i.e. from ftp, UNC shared path, local drive itself etc.
            fileStream.Seek(0, SeekOrigin.Begin);

            //Below three lines are very important as it will have the information about the file for browser.
            //without this information browser won't be able to open the file properly and this is what I was I talking about.
            String headerInfo = "attachment; filename=" + fileName;
            WebOperationContext.Current.OutgoingResponse.Headers["Content-Disposition"] = headerInfo;
            WebOperationContext.Current.OutgoingResponse.ContentType = MimeMapping.GetMimeMapping(fileName);

            return fileStream;
        }


        public void UploadFile(string fileName, Stream fileContent)
        {
           // Here you can have your own implementation to save file in different location i.e. FTP Server using ftp, 
           //shared server through UNC path or in the same server etc.
           UploadFileToLocation(fileName, fileContent)
        }
      
    }




This is about the service implementation and here is endpoint and behavior configuration for web.config I have. All important and crucial configurations settings are highlighted. It's difficult to explain all those settings one by one so I would recommend to go through MSDN and read about it if required.

  <system.web>
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2" maxRequestLength="2147483647" executionTimeout= "3600" />
    <httpModules>
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
    </httpModules>
  </system.web>  
<system.serviceModel>
    <services>
      <service name="P21.FileHandlingService.FileHandlerService">
        <endpoint address="" binding="webHttpBinding" behaviorConfiguration="restfulBehavior" 
                  contract="P21.FileHandlingService.IFileHandlerService" bindingConfiguration="WebHttpBindingConfig" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:81/Service" />
          </baseAddresses>
        </host>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
       </service>
    </services>
    <bindings>
      <webHttpBinding>
        <binding name="WebHttpBindingConfig" openTimeout="0:25:00" closeTimeout="0:25:00" sendTimeout="0:25:00" receiveTimeout="0:25:00" 
                 maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="5368709120" transferMode="Streamed">
          <readerQuotas maxDepth="2147483647"
                        maxStringContentLength="2147483647"
                        maxArrayLength="2147483647"
                        maxBytesPerRead="2147483647"
                        maxNameTableCharCount="2147483647"/>
          <security mode="None" />
        </binding>
      </webHttpBinding>     
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="restfulBehavior">
          <webHttp/>
          <dispatcherSynchronization asynchronousSendEnabled="true"/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>  
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <security>
      <requestFiltering>
        <!--IIS Settings-->
        <requestLimits maxAllowedContentLength="2147483648" />
      </requestFiltering>
    </security>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="ApplicationInsightsWebTracking" />
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
    </modules>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true" />
    <validation validateIntegratedModeConfiguration="false" />
  </system.webServer>   


These settings you can change/modify based on your needs, but you should know two important things here:
1. httpRuntime maxRequestLength : this is the setting which tells what's the maximum request length to send data. i.e. If I need to send data in chunks of 10MB file then it must set to >10MB. Hence all depends on chunks data size.
2. requestLimits maxAllowedContentLength: this the same settings at IIS server level.
3. binding maxReceivedMessageSize: This must be the maximum possible values of you file size which you want to upload.

Hence these values must be set accordingly.

You can test this service using jquery ajax call or C#.

You can consume this service through jquery ajax call or C#. Here is an example for jquery. But below jquery code doesn't have logic to chunking data. Hence this will fail if you want to send large file (i.e. >30 MB).
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="UTF-8" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script type="text/javascript">
        function UploadFile() {
            // grab your file object from a file input
            fileData = document.getElementById("fileUpload").files[0];

            $.ajax({
                url: 'http://localhost:81/Service1.svc/file?fileName=' + fileData.name,
                type: 'POST',
                data: fileData,
                cache: false,
                dataType: 'json',
                processData: false, // Don't process the files
                contentType: false, // Set content type to false as jQuery will tell the server its a query string request
                success: function (result) {
                    alert('successful..');
                },
                error: function (result) {
                    if (result.statusText === 'OK')
                        alert('successful..');
                    else
                        alert('Failed with reason: ' + result.statusText);
                }
            });

        }

        function DownloadFile(fileName, fileType) {

            var url = 'http://localhost:81/Service1.svc/file?fileName=' + fileName;
            window.location(url);             
        }

        function ListFiles()
        {
            $('#tblfiles').append('');
            $.ajax({
                url: 'http://localhost:81/Service1.svc/files', //wcf rest service which return files details.
                type: 'GET',
                cache: false,
                dataType: 'xml',
                processData: false, // Don't process the files
                contentType: false, // Set content type to false as jQuery will tell the server its a query string request
                success: function (result) {
                    var trHTML = '';
                    var i;
                    var x = result.getElementsByTagName("FileDetails");
                    for (i = 0; i < x.length; i++) {
                        var filename = x[i].childNodes[0].textContent;
                        var filesize = x[i].childNodes[2].textContent;
                        var fileType = x[i].childNodes[1].textContent;
                        trHTML += '<tr><td>' + filename + '</td><td>' + filesize + '</td><td>' + '<a href="#" onclick= "return DownloadFile(\'' + filename + '\',\'' + fileType + '\');">Download</a>' + '</td></tr>';
                    }
                    $('#tblfiles').append(trHTML);
                },
                error: function (result) {
                    alert('Failed with reason: ' + result.statusText);
                }
            });
        }
    </script>
</head>
<body>
    <div>
        <div>
            <input type="file" id="fileUpload" value="" />
            &nbsp;&nbsp;
            <button id="btnUpload" onclick="UploadFile()">
                Upload
            </button>
            <br/>
            <button id="btnList" onclick="ListFiles()">
                List Files
            </button>
        </div>
        <br/>
        <div id="filesdiv">
            <table id="tblfiles" border='1'>
                <tr>
                    <th>FileName</th>
                    <th>Size</th>
                    <th>#</th>
                    <!--<th>#</th>-->
                </tr>
            </table>
        </div>
    </div>
</body>
</html>


Note: You have to chunk the data if it is a large file. In this case above jquery code won't work as it tries to send whole data at one shot.

This is the rendered UI for above html.


What I have not shown in above service definition is "rest service method for getting the file details.". This is not a big deal and can be done easily in the way you want.

Here is the C# example which calls this service to upload a large video file (>1GB) and send data in chunks.
try
            {
                string fileName = "The_Angry_Birds_Movie_2016.mkv";
                HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://localhost:81/Service1.svc/file?fileName=" + fileName);
                Stream fileStream = File.OpenRead(@"C:\Personal\Movies\" + fileName);
                HttpWebResponse resp;

                req.Method = "POST";
                req.SendChunked = true;
                req.AllowWriteStreamBuffering = false;
                req.KeepAlive = true;
                req.Timeout = int.MaxValue; //this I did for safe side but it shouldn't be case in production.
                req.ContentType = MimeMapping.GetMimeMapping(fileName);
                // The post message header
                string strFileFormName = "file";
                string strBoundary = "———-" + DateTime.Now.Ticks.ToString("x");
                StringBuilder sb = new StringBuilder();
                sb.Append("–");
                sb.Append(strBoundary);
                sb.Append("\r\n");
                sb.Append("Content - Disposition: form - data; name =\"");
                sb.Append(strFileFormName);
                sb.Append("\"; filename =\"");
                sb.Append(fileName);
                sb.Append("\"");
                sb.Append("\r\n");
                sb.Append("Content - Type: ");
                sb.Append("application / octet - stream");
                sb.Append("\r\n");
                sb.Append("\r\n");

                string strPostHeader = sb.ToString();
                byte[] postHeaderBytes = Encoding.UTF8.GetBytes(strPostHeader);
                long length = postHeaderBytes.Length + fileStream.Length;

                req.ContentLength = length;
                req.AllowWriteStreamBuffering = false;

                
                Stream reqStream = req.GetRequestStream();
                
                // Write the post header
                reqStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);

                // Stream the file contents in small pieces (4096 bytes, max).

                byte[] buffer = new Byte[checked((uint)Math.Min(10485760, (int)fileStream.Length))]; //10 MB
                int bytesRead = 0;
                int count = 0;
                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    count += 10;
                    reqStream.Write(buffer, 0, bytesRead);
                    Console.WriteLine("DataWritten:" + count + "MB");
                }
                fileStream.Close();
                reqStream.Close();
                resp = (HttpWebResponse)req.GetResponse();
                
                Console.WriteLine(resp.StatusCode + ":"+ resp.StatusDescription);
            }
            catch(WebException ex)
            {
                Console.WriteLine(ex.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.ReadLine(); 
            }

Note: Above will handle upload/download for any type of files.

That's all. Thanks for reading. Feel free to provide your valuable feedback.



Wednesday, 1 June 2016

Dynamic Grid with Dynamic controls for Dynamic data using Telerik KendoUI MVC Grid.

Hi friends,

It was an requirement for one of my project and I had to work hard to achieve this. Hence thought it would be worth sharing with you all.

Problem Statement:
Grid should render data with proper controls (like dropdown for list, datepicker for date, checkbox for bool value etc) to provide edit/add feature in InCell mode (User should be able to edit data within the row).
Below picture will tell you what I mean:




As I said, I used telerik kendoUI ASP.NET MVC controls for this, so here are the prerequisite thing which you need.
1. Kendo.MVC.dll (reference for your project)
2. List of scripts files from KendoUI:
  • jquery.min.js (strongly recommended to use the one which you get from Telerik)
  • kendo.all.min.js
  • kendo.aspnetmvc.min.js 
These js files should be loaded in the same order as it is mentioned here because of dependency. Change in order will throw script error.

3. Use kendo css files for look and feel as per your choice.

These all you will get if you install Telerik KendoUI ASP.NET MVC controls by downloading it from Telerik here.



Here we go for solution:

Because of dynamism of data and controls, your most important task would be, designing the Model for Grid's template and data.

First thing you would need columns metadata information for grid so that you can design grid template for dynamic data and this is what you should have.

FEGridViewModel.cs

 public class FEGridViewModel
    {
        public List<Column> Columns { get; set; }
    }

    public class Column
    {
        public string ColumnName { get; set; }

        public ColumnType ColumnType { get; set; }

        public List<KeyValueData> ListData { get; set; }

        public bool Editable { get; set; }

        public bool Unique { get; set; }
    }

    public class KeyValueData
    {
        public string Name { get; set; }

        public string Value { get; set; }

    }
    public enum ColumnType
    {
        Normal,
        List,
        TrueFalse,
        DateTime
    }


Next we should design the view for grid where we will use this model to design the grid template.

View.cshtml
@model FastEditAPI.Models.FEGridViewModel

@(Html.Kendo().Grid<dynamic>()
.Name("dynamicGrid")
.Columns(columns =>
{
    foreach (var cols in Model.Columns)
    {
        if (cols.ColumnType == FastEditAPI.Models.ColumnType.List)
        {
            columns.ForeignKey(cols.ColumnName, new SelectList(cols.ListData, "Value", "Name", cols.ListData.First().Value)).EditorTemplateName("GridForeignKey")
            .Title(cols.ColumnName);
        }
        else if (cols.ColumnType == FastEditAPI.Models.ColumnType.TrueFalse)
        {
            columns.Template(@<text></text>).ClientTemplate("<input type='checkbox' #= " + cols.ColumnName + " ? checked='checked':'' # class='chkbx' />").Title(cols.ColumnName);
        }
        else if (cols.ColumnType == FastEditAPI.Models.ColumnType.DateTime)
        {
            columns.Bound(cols.ColumnName).Format("{0:dd/MM/yyyy}").EditorTemplateName("Date").Title(cols.ColumnName);
        }
        else
        {
            columns.Bound(cols.ColumnName).EditorTemplateName("String");
        }
    }
})
        .ToolBar(toolbar =>
        {
            toolbar.Save();
        })
        .Editable(editable => editable.Mode(GridEditMode.InCell))
        .Pageable()
        .Navigatable()
        .Sortable()
        .Scrollable()
        .DataSource(dataSource => dataSource
        .Ajax()
        .Batch(true)
        .PageSize(20)
        .ServerOperation(false)
        .Events(events => events.Error("error_handler"))
            .Model(model =>
            {
                foreach (var cols in Model.Columns)
                {
                    if (cols.Unique)
                        model.Id(cols.ColumnName);
                    if (!cols.Editable)
                        model.Field(cols.ColumnName, cols.Type).Editable(false);
                }
            })
            .Read(r => r.Action("feGrid_Read", "FE"))
            .Update(r => r.Action("feGrid_Update", "FE"))
            )



Here we go, Based on the column metadata code here will create controls. i.e. if column metadata says it's a List then code will create a drop down. Except this rest other templates are quite straight forward and the dropdown template can be only achieved here through ForeignKey concept.
 columns.ForeignKey(cols.ColumnName, new SelectList(cols.ListData, "Value", "Name", cols.ListData.First().Value)).EditorTemplateName("GridForeignKey")
            .Title(cols.ColumnName);
This ForeignKey concept requires an editor template which you should have under View=>Shared=>EditorTemplates folder with the name of "GridForeignKey" (this name you can provide with your choice but it must be same as provided in above code (as per your view). This is how GridForeignKey.cshtml should be:


GridForeignKey.cshtml
@model object        
@(
 Html.Kendo().DropDownListFor(m => m)      
        .BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)


Next important and interesting thing is model type for grid data which must be of type 'System.Dynamic.dynamic' so we can create dynamically a class of having same properties as the name of columns there in column metadata.

Now let's see how we are going to write/create dataset for grid with dynamic columns name.
Oops I forgot to tell you that, your main action controller's method which will render your view should return the model (I mean FEGridViewModel).

FEController.cs
public ActionResult Index()
        {
            FEGridViewModel model1 = new FEGridViewModel();
            model1.Columns = new List<Column>()
            {
                new Column() { ColumnName = "id", Type = typeof(String), Editable = false, Unique = true, ColumnType = ColumnType.Normal},
                new Column() { ColumnName = "name", Type = typeof(String), Editable = true, Unique = false, ColumnType = ColumnType.Normal},
                new Column() { ColumnName = "corp_name", Type = typeof(String), Editable = true, Unique = false, ColumnType = ColumnType.Normal},
                new Column() { ColumnName = "cc_currency_id", Type = typeof(String), Editable = true, Unique = false, ColumnType = ColumnType.List,
                    ListData = new List<KeyValueData> {
                        new KeyValueData { Name = "Dollars - USD", Value = "Dollars - USD" },
                        new KeyValueData { Name ="Other", Value ="Other" },
                        new KeyValueData { Name ="¥ yen", Value ="¥ yen" },
                        new KeyValueData { Name ="Zimbabwee Dollar", Value ="Zimbabwee Dollar" },
                        new KeyValueData { Name ="French Franc", Value ="French Franc" },
                    }
                },
                new Column() { ColumnName = "delete_flag", Type = typeof(String), Editable = true, Unique = false, ColumnType = ColumnType.List,
                ListData = new List<KeyValueData> {
                        new KeyValueData { Name = "Delete", Value ="Delete" },
                        new KeyValueData { Name = "Not Delete", Value ="Not Delete" },
                    }
                },
                new Column() { ColumnName = "date", Type = typeof(DateTime), Editable = true, Unique = false, ColumnType = ColumnType.DateTime },
                new Column() { ColumnName = "IsActive", Type = typeof(DateTime), Editable = true, Unique = false, ColumnType = ColumnType.TrueFalse },
            };

            return View(model1);
        }



And finally the grid dynamic data will be returned from the controller method "feGrid_Read" of "FE" controller (or whatever details provide in grid UI for event Read based on your code). This controller method will be called through Ajax call by Telerik. Thanks to Telerik to take care such things and making developer life easy.

Now let's create the data set for grid:

public ActionResult feGrid_Read([DataSourceRequest] DataSourceRequest request)
        {
            List<string> strList = new List<string>() { "Dollars - USD", "Other", "¥ yen", "Zimbabwee Dollar", "French Franc" };
            List<dynamic> flexiList = new List<dynamic>();

                for (var i = 1; i <= 30; i++)
                {
                    string curr = strList[new Random().Next(1, 5)];
                    var flexible = new ExpandoObject() as IDictionary<string, Object>; ;
                    flexible.Add("id", (100 + i).ToString());
                    flexible.Add("name", "Data0" + i.ToString());
                    flexible.Add("corp_name", "T");
                    flexible.Add("cc_currency_id", curr);
                    //flexible.Add("cc_currency", new KeyValueData() { Name = curr , Value = curr });
                    flexible.Add("delete_flag", "Not Delete");
                    flexible.Add("date", DateTime.Now.ToShortDateString());
                    flexible.Add("IsActive", i%2==0? true : false);
                    //flexible.Add("flags", new KeyValueData() { Name = "Not Delete", Value = "Not Delete" });
                    flexiList.Add(flexible);
                }
 DataSourceResult dsresult = (flexiList as IEnumerable<dynamic>).ToDataSourceResult(request);
            var serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new JavaScriptConverter[] { new ExpandoJSONConverter() });
            var json = serializer.Serialize(dsresult);
            return new MyJsonResult(json);
}


because of dynamic data we need to serialize data to json manually. Hence you will be required below two classes which I have used in above code, "ExpandoJSONConverter" and "MyJsonResult". Thanks to Telerik again for creating these two classes.

ExpandoJSONConverter.cs
 public class ExpandoJSONConverter : JavaScriptConverter
    {
        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            throw new NotImplementedException();
        }
        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            var result = new Dictionary<string, object>();
            var dictionary = obj as IDictionary<string, object>;
            foreach (var item in dictionary)
                result.Add(item.Key, item.Value);
            return result;
        }
        public override IEnumerable<Type> SupportedTypes
        {
            get
            {
                return new ReadOnlyCollection<Type>(new Type[] { typeof(System.Dynamic.ExpandoObject) });
            }
        }
    }


MyJsonResult.cs
public class MyJsonResult : ActionResult
    {

        private string stringAsJson;

        public MyJsonResult(string stringAsJson)
        {
            this.stringAsJson = stringAsJson;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            var httpCtx = context.HttpContext;
            httpCtx.Response.ContentType = "application/json";
            httpCtx.Response.Write(stringAsJson);
        }
    }


And we are done.

Thank You for reading. Feel free to provide your valuable feedback.

Sunday, 27 September 2015

What's New in C# 6.0


C# 6.0 has not introduced any new concepts like other versions of C# but instead it introduced some of very interesting and useful features which will help you to write more clean code with less typing.
I am sure as a developer you are going to love these features. Lets figure out what are those:



1. Getter-only auto Property.
 C# 6.0 allows you to define getter-only property and initialize it as part of constructor or directly.

class Features
{
        public string FirstName { get; }
        public string LastName { get; } = "Mahto";
        public Features()
        {
            FirstName = "Binod";
        }
}

2. Using static members: Use static with using directive for namespace reference.
It allow you to access static members of a type without having to qualify the access with the type name,

using static System.Math;

and now when you need to call say Sqrt, you don't need to write Math.Sqrt(...) instead just write Sqrt(...).
using CSharp6Features2.Day; //Here Day is an enum which I have defined.

so next time I don't need to specify Enum type 'Day' while calling it's property.

3. String interpolation: Get rid of using value tokens with "string.Format" to format string.
Example: Old way:

string fName = "Binod", lName = "Mahto";
Console.WriteLine(string.Format("My name is {0} {1}", fName, lName));

in C#6.0

string fName = "Binod", lName = "Mahto";
Console.WriteLine($"My name is {fName} {lName}");

4. Expression-bodied properties: Convert your methods or properties which returns data based on some calculation, to one line code like property using lambda expression.
for example:
Old way:
private double GetFullName(string fname, string lname)
{
         return fname + " " + lname;
}

in C# 6.0
public string FullName => $"{fname} {lname}";




5. Index Initializers: C# 6.0 has extended the object initializers to allow to set values to keys through any indexer that the new object has.
Example: Old Way:
public JObject ToJson()
{
       var obj = new JObject();
       obj["X"] = "Binod";
       obj["Y"] = "Mahto";
       return obj;
}

in C#6.0:
public JObject ToJson()
{
       var obj = new JObject() {["FName"] = "Binod",["LName"] = "Mahto" };
       return obj;
}
OR
public JObject ToJson() => new JObject() {["FName"] = "Binod",["LName"] = "Mahto" };

6. Null-conditional operators(?): It helps to avoid lot of codes which we write while accessing objects, like do null check for objects then do null check of that objects properties and so on. Let see the example:
Old way:
 public string FromJson(JObject json)
{
        if(json != null &&
            json["FName"] != null &&
            json["FName"].Type == JTokenType.String &
            json["LName"] != null &&
            json["LName"].Type == JTokenType.String)
         {
              return $"{json["FName"]} {json["LName"]}";
         }
         return string.Empty;
}

in C# 6.0
 public string FromJson(JObject json)
{
     if (json?["FName"]?.Type == JTokenType.String &&
          json?["LName"]?.Type == JTokenType.String)
     {
           return $"{json["FName"]} {json["LName"]}";
      }
      return string.Empty;
}

it is also very useful to do the event null check before triggering the event.
Ex: OnChanged?.Invloke(this, args);
in this case event will be triggered only if event is not null.

7. The nameof operator: There are scenarios when we need to know the name of program elements (property/parameter name), specially while throwing exceptions.
private static int Calculate(ABC obj)
{
       if (obj.y == 0)
            throw new DivideByZeroException(nameof(obj.y));
       else
           return obj.x / obj.y;
}

At last, this is the feature which I noticed in Visual Studio 2015 which impressed me a lot.
Your visual studio itself will let you know about some tips to clean your code (as Resharper does)
Ex: namespace references in using directive  which are not used. There are lot many, I am sure these features you are going to love it.

Till now I haven't encountered any such scenarios where I need the use of nameof operator.

That's it.

Thank You for reading. Feel free to give your feedback/comment.


Friday, 14 August 2015

Cross-Origin Requests (CORS) in ASP.NET Web API 2

Hello frnds,

In my previous post CRUD with AngularJS and ASP.Net Web API, I tried to show you, how to perform CRUD using AngularJs and ASP.NET web API.
In this example we had a ASP.NET Web API called 'Book API' and AngularJs views which talks to book api. As part of this example our web api and angularjs view both were part of same application. It means application and APIs both are running under same domain and port.

Now imagine, if our Book APIs are hosted in other domain and we need to consume it through AngularJS or Javascript/jquery app deployed/running in different domain. Problem looks very simple but fact is that we can't perform cross-origin/domain communication. So how to tackle this cross origin calls then, and the answer is using CORS  in ASP.NET Web API 2.





What is CORS?
Cross Origin Resource Sharing (CORS) is a W3C standard that allows a server to relax the same-origin policy. Using CORS, a server can explicitly allow some cross-origin requests while rejecting others. CORS is safer and more flexible than earlier techniques such as JSONP.

What is "Same Origin"?
Two URLs have the same origin if they have identical schemes, hosts, and ports. (RFC 6454)
These two URLs have the same origin:
http://example.com/foo.html
http://example.com/bar.html

These URLs have different origins than the previous two:
http://example.net - Different domain
http://example.com:9000/foo.html - Different port
https://example.com/foo.html - Different scheme
http://www.example.com/foo.html - Different subdomain

For details please visit: Enabling Cross-Origin Requests in ASP.NET Web API 2.

Now let's do the example.
On first step what we will do is, deploy our Book API (which we have created as part of above mentioned post 'CRUD with AngularJS and ASP.Net Web API'. and then our target will be to consume BooKAPIs from another application hosted with different domain or port.
I deployed my BookAPI to IIS and URL for BooKAPI for me is: "http://localhost:80/AngularJSExample/api/BookAPI".

Next let's create a simple asp.net application. For simplicity, In this application I am going to have a simple html page called "Home.html" and in this I wrote jqury code to access the BookAPI url to display all the books. Here is the code for Home.html.
<head>
    <title>CORS Example</title>
</head>
<body>
    <script src="Scripts/jquery-2.1.4.min.js"></script>
    <button id="btnGetBooks">Get Books</button>
    <div id="bookDiv"></div>
    
    <script>
        $(function () {

            var getBookList = function () {
                $.get(url).success(displayBooks).fail(displayErrors);
            };

            var displayBooks = function (data) {
                for (i = 0; i < data.length;i++) {
                    $("#bookDiv").append('Id=' + data[i].Id + ' Name=' + data[i].Name + ' Author=' + data[i].Author + '<br/>');
                }
            }

            var displayErrors = function (data) {
                $("#bookDiv").append(JSON.stringify(data, null, 1));
            }

            var url = "http://localhost/AngularJSExample/api/BookAPI"

            $("#btnGetBooks").click(getBookList);
        });
    </script>
</body>
</html>

Here is the UI for above code:

In above html, we have a button and on click of this button application will fetch books detail from BookAPI running under http://localhost:80/AngularJSExample/api.

In Html, I have a div which will show the result. On click of button I am calling the BookAPI using jquery $.get() method. For jquery, either you install directly to your application using nuget packages and refer it Or you can directly refer it through online CDN links.




Now I run it and click on 'Get Books' button then this is what you will see in page as output.



It means BookAPI is not allowing cross-origin communication. For your attention though both the application running under same host but ports are different. BookAPI running under port 80 and Home.html application running under port 81 and that's why asp.net web api (bookapi) is refusing the connection requested by port 81.
Here ASP.NET Web API 2 introduced the feature of CORS which makes our life easier on cross-origin connections.

To enable CORS feature for our BookAPI we need to follow few steps. Let's do it.

Follow below mentioned steps to enable CORS for your web api.
1. Install "Microsoft ASP.NET Web API  CORS" package using nuget package manager to you web api application project(please refer below screenshot here)



2. Open WebApiConfig.cs add settings to enable Cors by registering it to work it globally for all api controllers. To do this add below line of code to your 'Register' method:
config.EnableCors(new EnableCorsAttribute("*", "*", "GET"));
Here
first parameter '*' says, allows any orgin,
second parameter '*' says, allows any header,
third parameter 'GET' says, allows only GET methods.

3. OR go to individual API controller and enable it at controller/action method level and add 'EnableCors' attribute to the controller/action method as defined here:
[EnableCors("*","*","GET")]

'EnableCors' attribute presents under 'System.Web.Http.Cors' dll. So you include this you controller as
using System.Web.Http.Cors;

4. Deploy/update your app to IIS.

Now run Home.html page which we created as separate application and click on 'Get Books' button. Here is the result which we get:

That's it.

Thank You for reading. Feel free to give your feedback/comment.


Sunday, 26 July 2015

Asynchronous Programming with Async and Await in C# 5.0

There are lot of articles available over the internet on this topic. few of them are nicely explained but some makes you confusing on these terms.

Actually I was going through this concept and realized why don't I blog it for you to make it simple in understanding. So let me try to explain Asynchronous Programming with Async and Await in a way I understand.

Async and Await:
           These are two keywords of C# and It's introduced in C#5.0 as part of .NET Framework 4.5. These two keywords helps you to write asynchronous programming  code (which will see down here) without any delegate, event or threading complex logic. Actually C# does that complex job internally when you use Async and Await.
Looking into below given example, you will realize it is easy and equivalent as normal synchronous programming code. 

Before we proceed let me tell you few basic mandates about async and await:
  1. await can be used only inside async method (method defines with async keyword)
  2. async methods can use only void, Task or Task<T> as return type.
  3. A method can not awaited (we can't use await with method call), if method is not async and doesn't return a Task. 
  4. Always use 'Async' as suffix to your async methods. (this is not mandatory but a guideline which helps to differentiate async and normal methods) 



Let see the example.
Here I am going to create an async method which returns void. Only purpose of this method is to enable my method to use await inside this method.

public async void DoMyCalculation()
{
     int primeLimit = 10;
     Task<IEnumerable<int>> primeNumsTask = GetPrimeNumbersAsync(primeLimit);

     DoSomeTasksHere();

     IEnumerable<int> primeNums = await primeNumsTask;

     Console.WriteLine("Sum of all prime numbers from 1 to " + primeLimit + " is: " + primeNums.Sum());
}

This method will do lot of tasks/calculation including finding sum of prime numbers within a limit. Here my purpose is, I want to calculate sum of prime numbers asynchronously so that it will not stop/interrupt other tasks which might be written inside DoSomeTasksHere() like methods.

In above method,

Task<IEnumerable<int>> primeNumsTask = GetPrimeNumbersAsync(primeLimit);

Says, there is async method called ‘GetPrimeNumbersAsync’ which returns an IEnumerable list of prime numbers(int) within the range provided. But above code actually means, you will get the prime numbers only when you await the task using below line of code.

IEnumerable<int> primeNums = await primeNumsTask;

Here ‘GetPrimeNumbersAsync’ methods will initiate the execution and control will be returned to the calling method ‘DoMyCalculation()’ and control will move forward to execute ‘DoSomeTasksHere()’ method as per our code.
Now let see how we need to define our async method ‘GetPrimeNumbersAsync()’:

public async Task<IEnumerable<int>> GetPrimeNumbersAsync(int limit)
{
     Console.WriteLine("Start GetPrimeNumbersAsync() call");
         
     IEnumerable<int> primeNums = FindPrimeNumbers(limit);

     Console.WriteLine("End GetPrimeNumbersAsync() call");

     return primeNums;
}

private IEnumerable<int> FindPrimeNumbers(int limit)
{
      Console.Write("PrimeNumbers:");
      for (int i = 1; i <= limit; i++)
      {
           Thread.Sleep(1000);
           if (i % 2 == 0)
           {
               Console.Write(i + " ,");
               yield return i;
           }
      }
      Console.WriteLine();
}

So as per the concept, to define a method async we need to declare method with async keyword and return type should of Task<T> (In our case it is Task<IEnumerable<int>>.
That’s all. Here is the complete code:




namespace TestConsoleApp
{
    public class AsyncAwait
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main() call starts.");
            AsyncAwait program = new AsyncAwait();
            program.DoMyCalculation();
           
            Console.WriteLine("Main() call ends.");

            Console.ReadLine();
        }

        public async void DoMyCalculation()
        {
            int primeLimit = 10;
            Task<IEnumerable<int>> primeNumsTask = GetPrimeNumbersAsync(primeLimit);

            DoSomeTasksHere();

            IEnumerable<int> primeNums = await primeNumsTask;
            Console.WriteLine("Sum of all prime numbers from 1 to " + primeLimit + " is: " + primeNums.Sum());
        }

        public async Task<IEnumerable<int>> GetPrimeNumbersAsync(int limit)
        {
            Console.WriteLine("Start GetPrimeNumbersAsync() call");
         
            IEnumerable<int> primeNums = FindPrimeNumbers(limit);

            Console.WriteLine("End GetPrimeNumbersAsync() call");

            return primeNums;
        }

        private IEnumerable<int> FindPrimeNumbers(int limit)
        {
            Console.Write("PrimeNumbers:");
            for (int i = 1; i <= limit; i++)
            {
                Thread.Sleep(1000);
                if (i % 2 == 0)
                {
                    Console.Write(i + " ,");
                    yield return i;
                }
            }
            Console.WriteLine();
        }

        private void DoSomeTasksHere()
        {
            Console.WriteLine("DoSomeTasksHere() call : I am Sleeping.");
            Thread.Sleep(10000);
            Console.WriteLine("DoSomeTasksHere() end : I woke up.");
        }
    }

}

Now if you run the above program, this is what you will get as output in output window.

Main() call starts.
Start GetPrimeNumbersAsync() call
End GetPrimeNumbersAsync() call
DoSomeTasksHere() call : I am Sleeping.
DoSomeTasksHere() end : I woke up.
PrimeNumbers:2 ,4 ,6 ,8 ,10 ,
Sum of all prime numbers from 1 to 10 is: 30
Main() call ends.







Done.
Thank you for reading.
Feel free to provide your feedback/comments.

Reference: https://msdn.microsoft.com/en-us/library/hh191443.aspx