Sunday, November 19, 2017

Add glyphicon to Ajax.ActionLink() in ASP.NET MVC

Good evening!
Adding a Bootstrap glyphicon to Ajax.ActionLink() helper is similar with Html.ActionLink() except that when the linkText parameter of the helper is empty, it will cause an Ajax issue and an Internal Server Error will be thrown from the browser. If you're going to integrate glyphicons on Ajax.ActionLink() helper and exclude the linkText property, supply that parameter with space instead of empty string so as not to cause jQuery or Ajax issues.
@Ajax.ActionLink(" ", "DeleteComment", "Home",
    new { id = comment.CommentID },
    new AjaxOptions
    {
     OnBegin = "return confirm('Are you sure you want to delete this comment?');",
     InsertionMode = InsertionMode.Replace,
     UpdateTargetId = "event-details-" + Model.Id,
     HttpMethod = "GET",                                  
    }, new 
    {  
     @class = "commentDelete glyphicon glyphicon-trash"
    });
linkText is the first parameter of Ajax.ActionLink() helper.
Output:

Thursday, November 9, 2017

Invalid nested tag div found, expected closing tag input

Hello all,
I've been experimenting on how to print html document using the said 3rd party software called iTextSharp. iTextSharp is a popular tool and has several examples on the internet regarding integration to the project and occurring issues. One of the issue I encountered is Invalid nested div tag and is expecting a closing tag input. As I trace back my html source, the tags are well-formed except that they are self closing tags such as <input>, <hr>, <img>, <br> or the like. These tags when passed to an action method as string are not properly closed and thus an issue is thrown by iTextSharp's XMLWorkerHelper's ParseXHtml() method.
<img src="~/Images/success.png" /> 
<input type="hidden" name="OrderStatusHTML" />
<input type="submit" id="btnSubmit" value="Export to PDF" class="btn btn-success" />
The solution I came up with is to fix the page source using HTMLAgilityPack which is to explicitly close the tags by assigning HtmlElementFlag.Closed enum to HtmlNode.ElementsFlag["img"] dictionary.
[HttpPost]
[ValidateInput(false)]
public FileResult ExportToPDF(string OrderStatusHTML)
{
 HtmlNode.ElementsFlags["img"] = HtmlElementFlag.Closed;
 HtmlNode.ElementsFlags["input"] = HtmlElementFlag.Closed;
 HtmlDocument doc = new HtmlDocument();
 doc.OptionFixNestedTags = true;
 doc.LoadHtml(OrderStatusHTML);
 OrderStatusHTML = doc.DocumentNode.OuterHtml;

 using (MemoryStream stream = new System.IO.MemoryStream())
 {
  Encoding unicode = Encoding.UTF8;
  StringReader sr = new StringReader(OrderStatusHTML);
  Document pdfDoc = new Document(PageSize.A4, 10f, 10f, 100f, 0f);
  PdfWriter writer = PdfWriter.GetInstance(pdfDoc, stream);
  pdfDoc.Open();
  XMLWorkerHelper.GetInstance().ParseXHtml(writer, pdfDoc, sr);
  pdfDoc.Close();
  return File(stream.ToArray(), "application/pdf", "OrderStatus.pdf");
 }
}

That's it.. :-D

Tuesday, November 7, 2017

Add glyphicon to Html.ActionLink() in ASP.NET MVC

Hello,
Here's how to integrate glyphicon to Html.ActionLink() helper in ASP.NET MVC. The code below will display the glyphicon shopping cart right after the text Checkout of the anchor element.
@Html.ActionLink("Checkout", "Index", "Home", null, new { @class = "btn btn-info glyphicon glyphicon-shopping-cart" })
In order to add the glyphicon before the text of the anchor element, use @Url.Action() instead.
<a href="@Url.Action("Index", "Checkout")" class="btn btn-info">
 <span class="glyphicon glyphicon-shopping-cart" ></span>Checkout
</a>
Output:

Thursday, November 2, 2017

Formatting numbers using toLocaleString() in JavaScript

I've been using a JavaScript 3rd party library to format numbers with comma and decimal place(s). The JavaScript library called NumberFormatter was introduced to me by my developer with exceptional skills in front-end programming. Due to simplicity sake, I'm exploring options if this can be achieved using an existing JavaScript function instead of using the existing 3rd party app.

After doing some research, I found an answer here: How to use toLocaleString() and tofixed(2) in javascript which is to use toLocaleString() by setting the options minimumFractionDigits and maximumFractionDigits to 2.
Number.prototype.toLocaleFixed = function (n) {
    return this.toLocaleString(undefined, {
        minimumFractionDigits: n,
        maximumFractionDigits: n
    });
};
Sample usage:
var result = parseFloat(amount).toLocaleFixed(2)

Saturday, October 21, 2017

Task Management System with Entity Framework and ASP.NET MVC

Hello,
Here's a simple Task Management System with Entity Framework 6 taken from Udemy's Asp.Net MVC With Entity Framework From Scratch video tutorial. The output of the project should be in ASP.NET Webform but I chose to upload a sample in ASP.NET MVC which is intended for ASP.NET MVC developers. The entire source code can be downloaded here:Task Management System MVC. The project includes the stored procedure necessary to display the data through the grid. As for the database table, it is included in the tutorial series through a PDF file.
Cheers!

Monday, October 16, 2017

Ajax.ActionLink() not redirecting to ActionResult with Ajax Attribute

Given that I have this code in my .cshtml page using Ajax.ActionLink() that calls a controller method using Ajax request:
@Ajax.ActionLink("Select", "TaskListing", new { id = item.TaskID }, 
   new AjaxOptions(){ 
    HttpMethod = "GET",
    UpdateTargetId = "taskListing",
    InsertionMode = InsertionMode.Replace
})
And the controller method called by the Ajax ActionLink is decorated with Ajax attribute.
[HttpGet]
[AjaxOnly(true)]
[ActionName("TaskListing")]
public ActionResult TaskListing_Ajax(int id = -1)
{
 var projects = projRep.GetAllProjects();
 var model = new TaskAndTaskViewModel();
 model.Task = te.Tasks.FirstOrDefault(t => t.TaskID == id);
 model.SelectList = from p in projRep.GetAllProjects()
        select new SelectListItem
        {
         Selected = (p.ProjectID == Convert.ToInt32(model.Task.ProjectID)),
         Text = p.ProjectName.ToString(),
         Value = p.ProjectID.ToString()
        };

 return PartialView("TaskForm", model);
}
Normally, the request would push through. If does not proceed, maybe you have not added the Microsoft JQuery Unobtrusive Ajax to your project. Downloading and installing the said package(Microsoft JQuery Unobtrusive Ajax) via NuGet might fix the problem.

Sunday, October 8, 2017

Read .NET configuration files using NameValueSectionHandler and AppSettingsSection Types

Hello all,
I've read from a tutorial NameValueCollection and .NET Configuration Files which targets .NET 1.0/1.1 on how to read config files using type NameValueSectionHandler. I intend to explore more on applying this concept to recent versions of .NET frameworks. Upon doing some diggings, I came up with two options. First is using NameValueSectionHandler type and the other one is AppSettingsSections. To begin with, I have this App.config file with XML elements scriptsfiles and docfiles all registered in configSections.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="scriptfiles" type="System.Configuration.NameValueSectionHandler"/>
    <section name="docfiles" type="System.Configuration.AppSettingsSection"/>
  </configSections>
  <scriptfiles>
    <add key="C:\batchfiles\2017" value="*.bat" />
    <add key="C:\vbs\2017" value="*.vbs" />
  </scriptfiles>
  <docfiles>
    <add key="C:\applicants\2017" value="*.doc" />
    <add key="C:\officemanuals\2017" value="*.pdf" />
  </docfiles>
  <startup> 
      <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup> 
</configuration>
If you noticed, each sections are declared with different types specifically NameValueSectionHandler and AppSettingsSection with similar node structures. To read the element with type NameValueSectionHandler we use the ConfigurationManager.GetSection() method.
C# Code
private static void ReadNameValueSectionHandler()
{
 Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);            
 NameValueCollection scriptFiles = (NameValueCollection)ConfigurationManager.GetSection(config.GetSection("scriptfiles").SectionInformation.SectionName);
 foreach (var item in scriptFiles.AllKeys)
 {
  Console.WriteLine(String.Format("Key:{0}, value:{1}", item, scriptFiles[item]));
 }
}
For the element with AppSettingsSection type we simply cast the ConfigurationSection object to AppSettingsSection.
C# Code
private static void ReadAppSettingsSection()
{
 Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
 ConfigurationSection section = config.GetSection("docfiles");
 var scriptSettings = ((AppSettingsSection)section).Settings;    

 foreach (var item in scriptSettings.AllKeys)
 {
  Console.WriteLine(String.Format("Key:{0}, value:{1}", item, scriptSettings[item].Value));
 }
}

Saturday, October 7, 2017

Cannot convert type 'System.Configuration.ConfigurationSection' to 'System.Collections.Specialized.NameValueCollection'

Good evening!
I've tried casting the config object to NameValueCollection using .NET Framework 4.5.2 of Visual Studio 2015 which I read from a tutorial on how to read config files using type NameValueSectionHandler. However, as I use the code below to cast the ConfigurationSection object to NameValueCollection,
C# Code
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
NameValueCollection scriptFiles = (NameValueCollection)config.GetSection("scriptfiles");
I get an error which is the title of this post. It seems that the code was applicable to older versions of .NET Framework and not the recent ones.
After doing some research, I found out that the workaround is to use ConfigurationManager.GetSection() in which the parameter passed is the SectionName of the config object instead of directly casting the ConfigurationSection object returned by the config.GetSection() method.
C# Code
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);            
NameValueCollection scriptFiles = (NameValueCollection)ConfigurationManager.GetSection(config.GetSection("scriptfiles").SectionInformation.SectionName);            
Output That's it!

Friday, October 6, 2017

Call Stored Procedures from Entity Framework in ASP.NET MVC

Good day!
Here's an ASP.NET MVC example of a CRUD(Create/Update/Delete) application using stored procedures and Entity Framework 6.First, you need to perform steps 1-3 from this link Call Stored Procedures from Entity Framework 6 in C# (Part 1). For step 3, instead of creating a console application use ASP.NET MVC Empty project. Once done, the code for the controller and views are shown below:
CustomersController
private CustomerEntities db = new CustomerEntities();

// GET: Customers
public ActionResult Index()
{
 return View(db.Database.SqlQuery<Customer>("GetAllCustomers").ToList());
}

// GET: Customers/Create
public ActionResult Create()
{
 return View();
}

// POST: Customers/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "CompanyName,ContactName,Address,Country,Phone")] Customer customer)
{
 if (ModelState.IsValid)
 {
  db.Database.ExecuteSqlCommand("EXEC dbo.InsertCustomer @CompanyName,@ContactName,@Address,@Country,@Phone",
   new SqlParameter("CompanyName",customer.CompanyName),
   new SqlParameter("ContactName", customer.ContactName),
   new SqlParameter("Address", customer.Address),
   new SqlParameter("Country", customer.Country),
   new SqlParameter("Phone", customer.Phone));

  return RedirectToAction("Index");
 }

 return View(customer);
}

// GET: Customers/Edit/5
public ActionResult Edit(int? id)
{
 if (id == null)
 {
  return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
 }
 Customer customer = db.Customers.Find(id);
 if (customer == null)
 {
  return HttpNotFound();
 }
 return View(customer);
}

// POST: Customers/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "CustomerID,CompanyName,ContactName,Address,Country,Phone")] Customer customer)
{
 if (ModelState.IsValid)
 {
  db.Database.ExecuteSqlCommand("EXEC dbo.UpdateCustomer @CustomerID,@CompanyName,@ContactName,@Address,@Country,@Phone",
    new SqlParameter("CustomerID", customer.CustomerID),
    new SqlParameter("CompanyName", customer.CompanyName),
    new SqlParameter("ContactName", customer.ContactName),
    new SqlParameter("Address", customer.Address),
    new SqlParameter("Country", customer.Country),
    new SqlParameter("Phone", customer.Phone));

  return RedirectToAction("Index");
 }
 return View(customer);
}

// GET: Customers/Delete/5
public ActionResult Delete(int? id)
{
 if (id == null)
 {
  return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
 }
 Customer customer = db.Customers.Find(id);
 if (customer == null)
 {
  return HttpNotFound();
 }
 return View(customer);
}

// POST: Customers/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
 db.Database.ExecuteSqlCommand("EXEC dbo.DeleteCustomer @CustomerID",
   new SqlParameter("CustomerID", id));

 return RedirectToAction("Index");
}
Index.cshtml
<div class="container">
    <h2>Customer List</h2>

    <p>
        @Html.ActionLink("Create New", "Create", "Customers", new { @class = "btn btn-primary" })
    </p>
    <table class="table table-bordered table-condensed">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.CompanyName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ContactName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Address)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Country)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Phone)
            </th>
            <th>
                <span>Action</span>
            </th>
        </tr>

        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.CompanyName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.ContactName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Address)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Country)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Phone)
                </td>
                <td>
                    @Html.ActionLink("Edit", "Edit", new { id = item.CustomerID }, new { @class = "btn btn-info" })
                    @Html.ActionLink("Delete", "Delete", new { id = item.CustomerID }, new { @class = "btn btn-warning" })
                </td>
            </tr>
        }

    </table>

</div>
Create.cshtml
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>Customer Entry Form</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.CompanyName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CompanyName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.CompanyName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ContactName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ContactName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.ContactName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Address, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Address, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Address, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Country, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Country, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Country, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Phone, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Phone, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Phone, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn  btn-primary" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
Edit.cshtml
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>Edit Customer Record</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.CustomerID)

        <div class="form-group">
            @Html.LabelFor(model => model.CompanyName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CompanyName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.CompanyName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ContactName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ContactName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.ContactName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Address, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Address, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Address, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Country, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Country, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Country, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Phone, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Phone, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Phone, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
Delete.cshtml
<div class="container">
    <h4>Are you sure you want to delete this?</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.CompanyName)
        </dt>

        <dd>
            @Html.EditorFor(model => model.CompanyName, new { htmlAttributes = new { @class = "form-control", @readonly = "true", @style = "background-color:white;" } })
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.ContactName)
        </dt>

        <dd>
            @Html.EditorFor(model => model.ContactName, new { htmlAttributes = new { @class = "form-control", @readonly = "true", @style = "background-color:white;" } })
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Address)
        </dt>

        <dd>
            @Html.EditorFor(model => model.Address, new { htmlAttributes = new { @class = "form-control", @readonly = "true", @style = "background-color:white;" } })
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Country)
        </dt>

        <dd>
            @Html.EditorFor(model => model.Country, new { htmlAttributes = new { @class = "form-control", @readonly = "true", @style = "background-color:white;" } })
        </dd>

        <dt>
            @Html.DisplayNameFor(model => model.Phone)
        </dt>

        <dd>
            @Html.EditorFor(model => model.Phone, new { htmlAttributes = new { @class = "form-control", @readonly = "true", @style = "background-color:white;" } })
        </dd>

    </dl>

    @using (Html.BeginForm()) {
        @Html.AntiForgeryToken()

        <div class="form-actions no-color">
            <input type="submit" value="Delete" class="btn btn-danger" /> 
            @Html.ActionLink("Back to List", "Index", null, new { @class = "btn btn-primary"})
        </div>
    }
</div>
Expected Output
Source code: CallStoredProcedureWithASPMVC in Github

Wednesday, October 4, 2017

Call Stored Procedures from Entity Framework 6 in C# (Part 2)

In this second part of the series on how to call stored procedures from Entity Framework 6, I will demonstrate on executing them using context.Database methods. To accomplish this, you need to perform steps 1 through 3 from this article Call Stored Procedures from Entity Framework 6 in C#.
If you're done, the codes for the CRUD(Create, Update and Delete) functionalities are presented below.
private static CustomerEntities ce = new CustomerEntities();

private static void InsertCustomer()
{
 try
 {
  var result = ce.Database.ExecuteSqlCommand("EXEC dbo.InsertCustomer @CompanyName,@ContactName,@Address,@Country,@Phone",
   new SqlParameter("CompanyName", "TNT Bookstore"),
   new SqlParameter("ContactName", "Mr T."),
   new SqlParameter("Address", "Lincoln Village"),
   new SqlParameter("Country", "UK"),
   new SqlParameter("Phone", "42333"));

  if (result == 1)
  {
   Console.WriteLine("Insert Record Successful!");
  }
 }
 catch (Exception e)
 {
  //do something here
 }
}

private static void UpdateCustomer()
{
 try
 {                
  var result = ce.Database.ExecuteSqlCommand("EXEC dbo.UpdateCustomer @CustomerID, @CompanyName,@ContactName,@Address,@Country,@Phone",
   new SqlParameter("CustomerID", 12),
   new SqlParameter("CompanyName", "TNT Bookstore"),
   new SqlParameter("ContactName", "Mr M."),
   new SqlParameter("Address", "New Orleans"),
   new SqlParameter("Country", "USA"),
   new SqlParameter("Phone", "43567"));

  if (result == 1)
  {
   Console.WriteLine("Update Record Successful!");
  }
 }
 catch (Exception)
 {
  //do something here
 }
}

private static void DeleteCustomer()
{
 try
 {
  var result = ce.Database.ExecuteSqlCommand("EXEC dbo.DeleteCustomer @CustomerID",
   new SqlParameter("CustomerID", 12));
  if (result == 1)
  {
   Console.WriteLine("Delete Record Successful!");
  }
 }
 catch (Exception)
 {
  //do something here
 }
}

private static void GetAllCustomers()
{
 var results = ce.Database.SqlQuery<Customer>("GetAllCustomers", "").ToList();
 foreach (var item in results)
 {
  Console.WriteLine("ID:{0}, Company Name:{1}, Contact:{2}, Address: {3}, Country: {4}, Phone:{5}",
   item.CustomerID, item.CompanyName, item.ContactName, item.Address, item.Country, item.Phone);
  Console.Write("\n\n");
 }
}