Friday, August 29, 2014

NLog: Using NLog with a windows service

NLog: Using NLog with a windows service

Install Nlog through Nuget in the windows service project.
Install Nlog config through Nuget(it will be an empty file)

NLog library can be seen under References.

Nuget.config example:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"
       internalLogLevel="Trace"
      internalLogFile="C:\Users\njain\MailerLogs\log.txt"
      throwExceptions="false">

    <variable name="appName" value="YourAppName" />

    <targets async="true">
        <target xsi:type="File"
                name="logFile"
                layout="${longdate} - ${level:uppercase=true}:${logger} ${message}"
             
                fileName="${basedir}\logs\mailer.txt"
                keepFileOpen="false"
                archiveFileName="${basedir}\logs\Mailer_${shortdate}.{##}.txt"
               
                archiveNumbering="Sequence"
                archiveEvery="Day"
                maxArchiveFiles="10"
            />
     
    </targets>
    <rules>
        <logger name="*" writeTo="logFile" minlevel="Trace" />
    </rules>
</nlog>

Nlog.Config has two main sections- Target and Rules
Target has log location, name, and format settings and much more.
Rules describe when to log, where to log and at what level and much more.

To read more about NLog.config file - https://github.com/nlog/NLog/wiki/Configuration-file

Rebuild windows service project and Setup project, NLog.dll will be seen in the setup project.

IMPORTANT: Go to C;/Program Files(x86) and find the windowsServiceSetUp project and deploy the NLog.config file there. (Without it the windows service will not be able to write to the log file).



Other important settings to make sure logging works:
  1. NLog.config: ‘Copy to Output’ property needs to be set to ‘Copy Always’.
  2. ProjectInstaller: ‘Account’ property needs to be ‘LocalSystem’.


In the code the logger needs to be static so that it can be accessed all over the class.
Call the GetCurrentClassLogger() method to attach the logger to the current class.

partial class MailerService : ServiceBase
    {
 
       private static Logger logger = LogManager.GetCurrentClassLogger();
       
  public void Method()
        {
            logger.Info("Reading the table for mails");
           // string logName =logger.Name;

            ReadOutbox getData = new ReadOutbox();
            System.Data.DataSet ds = getData.GetMailIds();

            Email email = new Email();
            email.fromEmail = "from@from.com";
            email.fromName = "Mailer ex";
            email.smtpServer = "smtp.gmail.com";
            email.smtpCredentials = new System.Net.NetworkCredential("someemail@gmail.com", "*************");


            foreach (System.Data.DataRow dr in ds.Tables[0].Rows)
            {
                email.fromEmail = dr["From"].ToString();
                email.subject = dr["Subject"].ToString();
                email.HtmlBody = dr["HtmlBody"].ToString();
                email.mailBcc = dr["Bcc"].ToString();
                email.mailcc = dr["Cc"].ToString();
                email.replyTo = dr["ReplyTo"].ToString();
                email.toEmail = dr["To"].ToString();
                flag = true;

                if (email.fromEmail.Length == 0)
                {
                    logger.Info("Message SENT failed to - " + dr["EmailTo"].ToString() + " @ " + DateTime.Now + ". The sender field cannot be empty");
                    flag = false;
                    return;
                }

                if (email.toEmail.Length == 0)
                {
                    logger.Info("Message SENT failed to - " + dr["EmailTo"].ToString() + " @ " + DateTime.Now + ". The recipient field cannot be empty");
                    flag = false;
                    return;
                }

                if (!CheckRecipientEmail(email.toEmail))
                {
                    logger.Info("Message SENT failed to - " + dr["EmailTo"].ToString() + " @ " + DateTime.Now + ". Invalid email provided.");
                    flag = false;
                    return;
                }

                if (flag)
                {
                    bool result = email.sendEmail(dr["EmailTo"].ToString());
                    if (result == true)
                    {
                        logger.Info("Message Sent SUCCESS to - " + dr["EmailTo"].ToString());
                        return;
                    }
                    else
                    {
                        logger.Info("Message Sent FAILED to - " + dr["EmailTo"].ToString());
                    }
                } 
            }

            if (ds.Tables[0].Rows.Count == 0)
            {
                logger.Info("The mail queue is empty");
                logger.Info("Log file closed at " + DateTime.Now);
                logger.Info("=========================================");        
            }
        }

}




This will log the info messages in the log file when the windows service runs.

Monday, April 21, 2014

Implementing bit masking in C#



Requirement: Check the verified fields in contact and unverified fields should remain unchecked. Store the values as flags in a database table column.



Solution: Use bit-masking and store each flag as a bit in the 16-bit table column.

In Model: Define bool properties for each flag.
       
Public class details
{
   public bool EmailChked { get; set; }
   public bool OtherEmailChked { get; set; }
   public bool MobileChked { get; set; }
   public bool OtherMobilechked { get; set; }


 public details()
 {
   this.EmailChked = false;
   this.OtherEmailChked = false;
   this.MobileChked = false;
   this.OtherMobilechked = false;

 }

}


In your FillData method in repository(model)

After getting the value from the database table column compare and set:

if ((value & 1) > 0 )
        {
           ld.EmailChked = true;
         }

if ((value & 2) > 0)
         {
            ld.MobileChked = true;
         }
if ((value & 4) > 0)
         {
            ld.OtherMobilechked = true;
         }
if ((value & 8) > 0)
         {
            ld.OtherEmailChked = true;
         }





To save the flag status updation, in controller, in the POST action method
Use FormCollection and get the checked/unchecked status(to see how to get the checked/unchecked status from view to Controller, scroll down) and then pass the status to the save method.

Int16 status = 0;
            if (form["ChkEmail"].Contains("true"))
            {
                status |= 1;
            }
            else
            {
                status &= ~1;
            }

            if (form["ChkOtherEmail"].Contains("true"))
            {
                status |= 8;
            }
            else
            {
                status &= ~8;
            }

            if (form["ChkMobile"].Contains("true"))
            {
                status |= 2;
            }
            else
            {
                status &= ~2;
            }

            if (form["ChkOtherMobile"].Contains("true"))
            {
                status |= 4;
            }
            else
            {
                status &= ~4;
            }

         if (ModelState.IsValid)
            {           
                    Repository.VerificationStatus(status, id);
                     }





How to get the checked/unchecked status from view to Controller:

Use the checkbox’s string “name” and bool “IsChecked” parameters

<div>@Html.CheckBox("ChEmail", Model.OtherEmailChked)</div>
<div>@Html.CheckBox("ChOtherEmail", Model.OtherEmailChked)</div>
<div>@Html.CheckBox("ChMobile", Model.MobileChked)</div>
<div>@Html.CheckBox("ChOtherMobile ", Model.OtherMobileChked)</div>

When the FormCollection is passed to the controller each checkbox’s status can be known using:  form["keyName"].Contains("true")


                                        

MVC4 Validation (Client Side) using Ajax



Requirement: Validate the input by the user on client side.




Solution:
In the web.config check if the namespace is there, if not add it
<add namespace="System.Web.Mvc.Ajax" />

In the View add the following:
@section Scripts
{
    @Scripts.Render("~/bundles/jqueryval")
}



Add the “validationMessageFor” Html Helper like this-
<table width="100%">
  <tr>
    <td> 
      <div>First Name</div>                                                              
      <div>@Html.EditorFor(model =>  @item.FName)</div>
           @Html.ValidationMessageFor(model => @item.FName)
                                 
                                                                                   
                                          
      <div>Last Name</div>
      <div>@Html.EditorFor(model => @contact.LName)</div>
           @Html.ValidationMessageFor(model => @contact.LName)
     </td>
    </tr>                                                                                              
    <tr>
      <td><input type="submit" title="Save" /></td>
    </tr>
  </table>

In the Model:
[Required( ErrorMessage = "First Name is required.") ]
  public String FName { get; set; }

[Required]
   public String LName { get; set; }

[RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                   @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                   @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$",
                   ErrorMessage = "Email is not valid")]
   public String Email { get; set; }

//other way of using Email data annotation
[DataType(DataType.EmailAddress, ErrorMessage = "E-mail is not valid")]
   public String OtherEmail { get; set; }

      
[DataType(DataType.PhoneNumber)]
[RegularExpression(@"^(\d{10})$", ErrorMessage = "Please enter proper phone
                   number.")]                   
   public String Mobile { get; set; }


[RegularExpression(@"^(\d{5}(-\d{4})?$)|(^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1}
                   *\d{1}[A-Z]{1}\d{1})$", ErrorMessage = "Invalid Zip")]           
   public String Postal { get; set; }

      

LINQ to display list of values separated by a comma



Requirement: We need to display data as a single row of values separated by commas.

Solution:
   Object obj = new Object();

var dbquery = (from g in db.table1
               join gc in db.table2
               on g.id equals gc.id
               where g.prop1 == value1 && gc.prop2 == value2
               select g);

          if (dbquery!= null && dbquery.Count() > 0)
            {
         // Gets all the groups/tags the lead belongs to and joins them with a ','
                obj.PropName=string.Join(",",dbquery.Select(x=>                                                x.propName)); 
           

            }

Formatting DateTime type to display just the date in C#

                     Formatting DateTime type to display just the date.

Requirement: To display just the date using the object of DateTime type.

Solution: Declare a string type variable to hold the date.

                   public String NextDate { get; set; }

             
        NextDate = string.Format("{0:MM/dd/yyyy}", DateTimeVariableToBeFormatted)


It will let you display the DateTime format of “4/30/2014 12:00:00 AM” type to

Date format “04/30/2014”

Jquery DatePicker in MVC4

Jquery DatePicker in MVC4 (Displaying the calendar and capturing the selected value to save it)

Requirement:
Show the date on in a view and this display should allow user to set a new date using a calendar. The calendar should show on the click of the textbox where the date is displayed.



Solution:
For the view
In the _Layout.cshtml(which resides in the Shared folder under Views) ,define
@RenderSection("scripts", required: false)

In the view where the datepicker is defined, use the follwing jQuery code

@section scripts{
 <script type="text/javascript">
     $(function () {
         $("#txtNewDate").datepicker({
             onSelect: function (date) { $("#_newDate").val(date) }

         });
     });
</script>


To format the styling (size, font etc) of the ui-datepicker, include the following code:

<style type="text/css">
    .ui-datepicker {
        font-family:Garamond;
        font-size: 12px;
        margin-left:10px
     }
 </style>



In the form tag, define a hidden field to capture the new date, also get the current date value from the database

@using (@Html.BeginForm())
{
       <input type="hidden" id="_newDate" name="_ newDate "/> 


<div>

                            <div>Date:</div><div ><input style="width:5em;height:2em; " type="text" id=" txtNewDate "  value="@Html.Raw(Model.NextCall)"/></div>
                            </div>
<div>
                               <div><input type="submit" style="height:2em" value="save" name="save" title="Save" id="btnSave" /></div>                              
                            </div>

}

For the Controller:

In the POST action method , use formCollection
[HttpPost]
[ActionName("details")]
 public ActionResult details_Post(int id, FormCollection form)
        {
//define a datetime variable
DateTime Nxtdate = DateTime.MinValue;

if (form["_newDate "] != "")
            {
               //convert the form variable containing date to datetime type
 Nxtdate = Convert.ToDateTime(form["_newDate "]);
            }


if (ModelState.IsValid)
            {
                //call method to update the date
                Repository.SaveDate(Nxtdate);

             
            }
Return view();


}




For the Repository(Model):
Saving the NewDate

  public static void SaveDate(DateTime NxtCall, int Id)
        {

            try
            {
                   //open the connection
                    using (SWSData db = new ef.SWSData())
                    {
                        //get the row to be updated
                        var dbDate = db.Date.SingleOrDefault(ld => ld.id == Id);

                        if ( dbDate != null)
                        {
                            if (NxtCall != DateTime.MinValue)
                            {
                                dbDate.CallDate = NxtCall;
                            }
                           
                       }

                        //if the data does not exist already, insert a new record for the same.
                        else
                        {
                            Date ld = new Date()
                            {
                                CallDate = NxtCall,
                               
                            };

                            db.AddToDate(ld);

                           
                        }
                        //save changes to database
                        db.SaveChanges();
                    }
               
            }

            catch (Exception ex)
            {

                if (HttpContext.Current.IsDebuggingEnabled)
                {

                    throw ex;
                }
            }

        }