Showing posts with label ASP.Net MVC. Show all posts
Showing posts with label ASP.Net MVC. Show all posts
Thursday, June 15, 2017
Why use async/await pattern?
While code execution is waiting for an IO bound operation, such as SQL or HTTP operation, to complete, the thread that is waiting can be used by other code operations. Basically, mark the method as async and await the results of an IO bound operation. While waiting, the awaited thread can be utilized for other operations.
Labels:
ASP.Net MVC,
C#
Tuesday, October 25, 2016
ASP.NET MVC: Setting and removing cookies
// For session-only cookie, set expires to null
void SetCookie(string cookieName, string value, DateTime expires)
{
HttpCookie cookie = new HttpCookie(cookieName, value);
cookie.Expires = expires;
HttpContext.Response.Cookies.Remove(cookieName);
HttpContext.Response.SetCookie(cookie);
}
void RemoveCookie(string cookieName)
{
if (this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains(cookieName))
{
HttpCookie cookie = this.ControllerContext.HttpContext.Request.Cookies[cookieName];
cookie.Expires = DateTime.Now.AddYears(-1);
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
}
}
string GetCookieVal(string cookieName)
{
if (this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains(cookieName))
{
HttpCookie cookie = this.ControllerContext.HttpContext.Request.Cookies[cookieName];
return cookie.Value;
}
return null;
}
void SetCookie(string cookieName, string value, DateTime expires)
{
HttpCookie cookie = new HttpCookie(cookieName, value);
cookie.Expires = expires;
HttpContext.Response.Cookies.Remove(cookieName);
HttpContext.Response.SetCookie(cookie);
}
void RemoveCookie(string cookieName)
{
if (this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains(cookieName))
{
HttpCookie cookie = this.ControllerContext.HttpContext.Request.Cookies[cookieName];
cookie.Expires = DateTime.Now.AddYears(-1);
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
}
}
string GetCookieVal(string cookieName)
{
if (this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains(cookieName))
{
HttpCookie cookie = this.ControllerContext.HttpContext.Request.Cookies[cookieName];
return cookie.Value;
}
return null;
}
Labels:
ASP.Net MVC
Wednesday, June 8, 2016
ASP.Net MVC Multiple submit buttons on a Form
// Form markup
<input name="submit" type="submit" value="Download" class="btn btn-primary" />
<input name="submit" type="submit" value="Display" class="btn btn-primary" />
// Controller processor
public ActionResult SomeReport(SomeModel model,string submit)
{
if (submit == "Display")
{
return View(model);
}
else if (submit == "Download")
{
return DownloadReport(model);
}
}
ActionResult DownloadRevenueReport(RevenueReportListModel model)
{
return File(Encoding.UTF8.GetBytes(GetTextData(model)),
"application/text", "Report.csv");
}
<input name="submit" type="submit" value="Download" class="btn btn-primary" />
<input name="submit" type="submit" value="Display" class="btn btn-primary" />
// Controller processor
public ActionResult SomeReport(SomeModel model,string submit)
{
if (submit == "Display")
{
return View(model);
}
else if (submit == "Download")
{
return DownloadReport(model);
}
}
ActionResult DownloadRevenueReport(RevenueReportListModel model)
{
return File(Encoding.UTF8.GetBytes(GetTextData(model)),
"application/text", "Report.csv");
}
Labels:
ASP.Net MVC
Tuesday, June 7, 2016
ASP.Net MVC HTTP GET Controller Action Processing Pattern for Reports or Searches
Scenario
- Select a month
- Days of month are displayed on the same view
Controller
[HttpGet]public ActionResult Index(ReportPageSelectionModel model, string msg)
{
String preSelectedMonth = null;
try
{
ViewBag.Msg = msg;
if (model.DisplayResults == false)
{
model.MonthList = ReportPageModelFactory.GetMonthList();
return View(model);
}
else
{
preSelectedMonth = model.SelectedMonth;
model.MonthList = ReportPageModelFactory.GetMonthList();
ReportPageResultModel resultModel =
ReportPageModelFactory.GetResultsModel(model.SelectedMonth);
ViewBag.Result = resultModel;
return View(model);
}
}
catch (Exception ex)
{
return RedirectToAction("Index", new { Msg = GetInnerMostException(ex).Message, SelectedMonth = preSelectedMonth });
}
}
Exception GetInnerMostException(Exception ex)
{
if (ex.InnerException == null)
return ex;
return GetInnerMostException(ex.InnerException);
}
View
@model ReportPageSelectionModel@using ReportPage.Models
@{
ViewBag.Title = "Report Page";
}
<div>
<h3>Criteria Selection</h3>
@using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
<div class="control-label col-md-3"><strong>@Html.LabelFor(model => model.SelectedMonth)</strong></div>
<div class="col-md-9">
<div class="form-control-static">
@Html.DropDownListFor(model => model.SelectedMonth, Model.MonthList)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-4 col-md-8">
<input type="hidden" name="DisplayResults" value="true" />
@Html.ActionLink("Reset", "Index", null, new { @class = "btn btn-default" })
<input type="submit" value="Go" class="btn btn-primary" />
</div>
</div>
</div>
}
@if (@ViewBag.Msg != null)
{
<div class="alert alert-danger">
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
<strong>@ViewBag.Msg</strong>
</div>
}
</div>
<hr />
@{
var result = @ViewBag.Result as ReportPageResultModel;
}
@if (result != null)
{
<div>
<h3>Result</h3>
@foreach(var day in result.Result)
{
<p>@day</p>
}
</div>
}
@section scripts
{
<script>
$(function () {
$("#SelectedMonth").change(function () {
$("form").submit();
});
});
</script>
}
Models
public class ReportPageSelectionModel{
[DisplayName("Month")]
[Required]
public string SelectedMonth { get; set; }
public List<SelectListItem> MonthList { get; set; }
public bool DisplayResults { get; set; }
}
public class ReportPageResultModel
{
public DateTime SelectedMonth { get; set; }
public List<string> Result { get; set; }
}
Model Factories
static public class ReportPageModelFactory{
static public ReportPageResultModel GetResultsModel(string selectedMonthStr)
{
var model = new ReportPageResultModel();
model.SelectedMonth = DateTime.Parse(selectedMonthStr);
model.Result = new List<string>();
for (int i=1; i<= DateTime.DaysInMonth(model.SelectedMonth.Year, model.SelectedMonth.Month); i++)
{
DateTime day = new DateTime(model.SelectedMonth.Year, model.SelectedMonth.Month, i);
model.Result.Add(day.ToString("dddd MMMM d, yyyy"));
}
return model;
}
static public List<SelectListItem> GetMonthList()
{
var monthList = new List<SelectListItem>();
for (int i = 1; i <= 12; i++)
{
DateTime month = new DateTime(DateTime.UtcNow.Year, i, 1);
monthList.Add(
new SelectListItem()
{
Text = String.Format("{0} {1}", month.Year, month.ToString("MMMM")),
Value = month.ToString()
});
}
return monthList;
}
}
Labels:
ASP.Net MVC
Wednesday, February 3, 2016
ASP.NET MVC: Creating and downloading MS Excel File
#region Controller Action
public ActionResult Index()
{
// Download link displayed on this view
//<h2>@Html.ActionLink("Download", "Download")</h2>
return View();
}
public ActionResult Download()
{
var data = new List<DataRow>
{
new DataRow{Date = DateTime.Now, Amount = 1M, Note = "Good, one"},
new DataRow{Date = DateTime.Now, Amount = 2M}
};
string reportName = "SampleReport_" + DateTime.Now.ToString();
string reportNameCleansed = RemoveInvalidChars(reportName);
return File(Encoding.UTF8.GetBytes(GetCSVReportData(data)),
"application/text", reportNameCleansed + ".csv");
}
#endregion
#region Helpers
class DataRow
{
public DateTime Date { get; set; }
public Decimal Amount { get; set; }
public string Note { get; set; }
}
string RemoveInvalidChars(string fileName)
{
string ret = string.Empty;
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
ret = fileName.Replace(c, '-');
}
return ret;
}
string GetCSVReportData(List<DataRow> data)
{
var fileData = new StringBuilder();
fileData.AppendLine("Date,Amount,Note");
foreach (var item in data)
{
fileData.AppendFormat("{0},{1},\"{2}\"",
item.Date.ToString("yyyy-MM-dd"),
item.Amount.ToString("########0.0000"),
item.Note);
fileData.AppendLine();
}
return fileData.ToString();
}
#endregion
public ActionResult Index()
{
// Download link displayed on this view
//<h2>@Html.ActionLink("Download", "Download")</h2>
return View();
}
public ActionResult Download()
{
var data = new List<DataRow>
{
new DataRow{Date = DateTime.Now, Amount = 1M, Note = "Good, one"},
new DataRow{Date = DateTime.Now, Amount = 2M}
};
string reportName = "SampleReport_" + DateTime.Now.ToString();
string reportNameCleansed = RemoveInvalidChars(reportName);
return File(Encoding.UTF8.GetBytes(GetCSVReportData(data)),
"application/text", reportNameCleansed + ".csv");
}
#endregion
#region Helpers
class DataRow
{
public DateTime Date { get; set; }
public Decimal Amount { get; set; }
public string Note { get; set; }
}
string RemoveInvalidChars(string fileName)
{
string ret = string.Empty;
foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
ret = fileName.Replace(c, '-');
}
return ret;
}
string GetCSVReportData(List<DataRow> data)
{
var fileData = new StringBuilder();
fileData.AppendLine("Date,Amount,Note");
foreach (var item in data)
{
fileData.AppendFormat("{0},{1},\"{2}\"",
item.Date.ToString("yyyy-MM-dd"),
item.Amount.ToString("########0.0000"),
item.Note);
fileData.AppendLine();
}
return fileData.ToString();
}
#endregion
Labels:
ASP.Net MVC,
C#
Friday, January 29, 2016
ASP.NET MVC: Data Binding a collection of items (parent with child rows)
Scenario
- Client is the parent record
- A client can have one or more contacts
- Contact is the child record
Models
Parent Record
public class ClientModel{
// Parent Record - Attributes
// Db-wise: Id is the primary key,
// serves as foreign key for child records
public int Id { get; set; }
public string ClientName { get; set; }
// Child Records
public List<ContactModel> Contacts { get; set; }
public ClientModel()
{
Contacts = new List<ContactModel>();
}
}
Child Record
public class ContactModel{
// Each child record has a temporary unique id to facilitate binding
public ContactModel()
{
this.GUID = Guid.NewGuid().ToString();
}
// Helper to form control id.
// e.g. [50e32e2b-a9af-45ec-8be5-97ffa219dae8].FirstName
public string ControlId(string controlName)
{
return string.Format("[{0}].{1}", this.GUID, controlName);
}
public string GUID { get; set; }
// Attributes of child record
// Db-wise: Foreign key is the Client Id
// Primary key is auto generated id
public string FirstName { get; set; }
public string LastName { get; set; }
}
Views
Client.cshtml
@using MvcMultipleItemDataBinding.Models@model ClientModel
@{
ViewBag.Title = "Client";
}
<h2>Client</h2>
@using (Html.BeginForm())
{
@Html.HiddenFor(m => m.Id)
@Html.LabelFor(model => model.ClientName)
@Html.TextBoxFor(model => model.ClientName)
<h3>Contacts</h3>
<table>
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
</tr>
</thead>
<tbody>
@foreach (var contact in Model.Contacts)
{
@Html.Partial("_Contacts", contact);
}
</tbody>
</table>
<input type="submit" value="Submit" />
}
_Contacts.cshtml
@using MvcMultipleItemDataBinding.Models@model ContactModel
<tr>
<td>
@*index of one of the items in the array of items*@
@*index.value = 50e32e2b-a9af-45ec-8be5-97ffa219dae8*@
@Html.Hidden(name: "index", value: @Model.GUID)
@*e.g. [50e32e2b-a9af-45ec-8be5-97ffa219dae8].FirstName*@
@Html.TextBox(@Model.ControlId("FirstName"), Model.FirstName)
</td>
<td>@Html.TextBox(@Model.ControlId("LastName"), Model.LastName)</td>
</tr>
Controller Actions
[HttpGet]
public ActionResult Client()
{
var model = new ClientModel();
// Display 2 blank rows
model.Contacts.Add(new ContactModel());
model.Contacts.Add(new ContactModel());
return View(model);
}
[HttpPost]
public ActionResult Client(ClientModel model)
{
TryUpdateModel(model.Contacts);
return View(model);
}
Labels:
ASP.Net MVC
Friday, December 11, 2015
ASP.NET MVC: Getting data or partial view from a controller method with an Ajax call
Points of Interest
- Fetch raw data (current time utc and ticks) from server
- Fetch fully formed html created using partial view on the server
- Result is retrieved as JSON object from the Server onto the client
- Client code sets appropriate divs with the returned data
- Uses $.getJSON jquery method (a short hand for $.ajax)
- To get and execute script, $.getScript jquery method
Model
DateTime (now)Controller - Method to display Main Page
public ActionResult Index(){
return View();
}
Controller - Method to return JSON data
public JsonResult GetTime(){
var now = DateTime.UtcNow;
string viewString = RenderViewToString(this.ControllerContext, "_TimePartialView", now, true);
return Json(new
{
TimeUtc = now.ToShortDateString() + " " + now.ToShortTimeString(),
TimeTicks = now.Ticks,
TimePartialView = viewString
}, JsonRequestBehavior.AllowGet);
}
Controller - Helper method to create partial view as string
static string RenderViewToString(ControllerContext context,string viewPath,
object model = null,
bool partial = false)
{
ViewEngineResult viewEngineResult = null;
if (partial)
viewEngineResult = ViewEngines.Engines.FindPartialView(context, viewPath);
else
viewEngineResult = ViewEngines.Engines.FindView(context, viewPath, null);
if (viewEngineResult == null)
throw new FileNotFoundException("View cannot be found.");
var view = viewEngineResult.View;
context.Controller.ViewData.Model = model;
string result = null;
using (var sw = new StringWriter())
{
var ctx = new ViewContext(context, view,
context.Controller.ViewData,
context.Controller.TempData,
sw);
view.Render(ctx, sw);
result = sw.ToString();
}
return result;
}
Partial View (_TimePartialView)
@model DateTime<h2>Using Partial View from Server</h2>
<div class="row">
<div class="col-md-4">
<h3>Current Time UTC</h3>
</div>
<div class="col-md-4">
<h3>Current Time Ticks</h3>
</div>
</div>
<div class="row">
<div class="col-md-4">
@Model.ToShortDateString() @Model.ToShortTimeString()
</div>
<div class="col-md-4">
@Model.Ticks
</div>
</div>
Main View
@{ViewBag.Title = "Home Page";
}
<h2>Using Raw Data from Server</h2>
<div class="row">
<div class="col-md-4">
<h3>Current Time UTC</h3>
<div id="current_time_utc"></div>
</div>
<div class="col-md-4">
<h2>Current Time Ticks</h2>
<div id="current_time_ticks"></div>
</div>
<div class="col-md-4">
<h3>Update Async</h3>
@Html.ActionLink("Update", "GetTime", null, new { @class = "btn btn-primary", id = "UpdateBtn" })
</div>
</div>
<hr/>
<div id="time_partial_view"></div>
@section Scripts {
<script>
function fmtJSON(data) {
return JSON.stringify(data, null, 2);
}
$(function () {
$('#UpdateBtn').click(function (event) {
event.preventDefault();
var url = "/Home/GetTime";
var getting = $.getJSON(url, null);
getting.done(function (json) {
console.log('got data\n' + fmtJSON(json));
$('#current_time_utc').html(json.TimeUtc);
$('#current_time_ticks').html(json.TimeTicks);
$('#time_partial_view').html(json.TimePartialView);
});
getting.fail(function (jqxhr, textStatus, error) {
console.log("FAIL handler\njqXHR:\n" + fmtJSON(jqxhr) +
"\ntextStatus:\n" + textStatus +
"\nerrorThrown:\n" + error);
});
getting.always(function () { console.log("remove wait cursor"); });
});
});
</script>
}
Output Before Update

Output After Update
Successful Data Transmission
{"TimeUtc": "12/11/2015 5:23 PM",
"TimeTicks": 635854514161656600,
"TimePartialView": "<h2>Using Partial View from Server</h2>\r\n<div class=\"row\">\r\n <div class=\"col-md-4\">\r\n <h3>Current Time UTC</h3>\r\n </div>\r\n <div class=\"col-md-4\">\r\n <h3>Current Time Ticks</h3>\r\n </div>\r\n</div>\r\n\r\n<div class=\"row\">\r\n <div class=\"col-md-4\">\r\n 12/11/2015 5:23 PM\r\n </div>\r\n <div class=\"col-md-4\">\r\n 635854514161656592\r\n </div>\r\n</div>\r\n"
}
Failure
jqXHR:{
"readyState": 4,
"responseText": "<!DOCTYPE html>\r\n<html>\r\n <head>\r\n ....
[Exception: bad]\r\n ASPNetMvcAjaxGet.Controllers.HomeController.GetTime() in c:\\Temp\\ASPNetMvcAjaxGet\\ASPNetMvcAjaxGet\\Controllers\\HomeController.cs:18\r\n lambda_method(Closure , ControllerBase , Object[] ....",
"status": 500,
"statusText": "Internal Server Error"
}
textStatus:
error
errorThrown:
Internal Server Error
Labels:
ASP.Net MVC
Thursday, December 10, 2015
ASP.NET MVC: Posting to controller method with an Ajax call
Points of Interest
- GET method for displaying form using a Razor view that contains JavaScript for POSTing data asynchronously.
- POST method for saving changes - a regular ASP.NET MVC Controller method that returns JSON
- jQuery $.post for posting values to the POST method
- $.post is a shortcut method for .ajax
- See $.get and $.load shortcut methods for GETting data from the Server
- $.load retrieves and loads data into a DOM element in one shot. For example, retrieve a partial view from server display in a div.
Model
public class ContactViewModel{
[Required]
public string Name { get; set; }
[Required]
public string Phone { get; set; }
}
Controller
public class HomeController : Controller{
// Display the form for user entry
[HttpGet]
public ActionResult Index(ContactViewModel model)
{
return View(model);
}
// Invoked with an Ajax Call from the form
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Index(ContactViewModel model, FormCollection collection)
{
if (ModelState.IsValid)
{
// all good, save changes, return any data you want to show to user via js
return Json(new { success = true });
}
// validation failed - set status code and return error information
Response.StatusCode = (int) HttpStatusCode.BadRequest;
return Json(new { success = false, error = "Validation failed" });
}
}
View
@model ASPNetMVCAjaxPost.Models.ContactViewModel@{
ViewBag.Title = "Contact Form";
}
<h3>Contact Form</h3>
@using (Html.BeginForm("Index", "Home", FormMethod.Post,
new { @class = "form-horizontal", role = "form", name = "ContactForm" }))
{
@Html.AntiForgeryToken()
<div class="form-group">
@Html.LabelFor(m => m.Name, new { @class = "col-sm-2 control-label" })
<div class="col-sm-10">
@Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Phone, new { @class = "col-sm-2 control-label" })
<div class="col-sm-10">
@Html.TextBoxFor(m => m.Phone, new { @class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
}
@section Scripts {
<script>
function fmtJSON(data) {
return JSON.stringify(data, null, 2);
}
$(
function () {
$('form').submit(
function (event) {
event.preventDefault();
var formData = $('form').serializeArray();
var url = '/Home/Index';
var posting = $.post(url, formData);
posting.done(function (data, textStatus, jqXHR) {
alert("DONE handler\ndata:\n" + fmtJSON(data) +
"\ntextStatus:\n" + textStatus +
"\njqXHR:\n" + fmtJSON(jqXHR));
});
posting.fail(function (jqXHR, textStatus, errorThrown) {
alert("FAIL handler\njqXHR:\n" + fmtJSON(jqXHR) +
"\ntextStatus:\n" + textStatus +
"\nerrorThrown:\n" + errorThrown);
});
}
);
}
);
</script>
}
Form
Failure

Success
Labels:
ASP.Net MVC
Tuesday, November 24, 2015
ASP.Net MVC: Display custom, dynamically queried field names
Controller Method
public ActionResult Contact(){
return View(new ContactViewModel()
{
MarketingEmail = "marketing@example.com",
SupportEmail = "support@example.com"
});
}
ViewModel
public class ContactViewModel
{
[Display(Name="SupportEmailLabel", ResourceType=typeof(CustomFieldNames))]
public String SupportEmail { get; set;
}
[Display(Name =
"MarketingEmailLabel", ResourceType = typeof(CustomFieldNames))]
public String MarketingEmail { get;
set; }
}
Field Name Provider Class
static public class CustomFieldNames
{
static public string SupportEmailLabel
{
get
{
// This label can be retrieved from the database or application cache
// The label can be varied by each user
return "Help email address";
}
}
static public string MarketingEmailLabel
{
get
{
return "Marketing email address";
}
}
}
View
@model MvcWebAppCustomFieldNames.Models.ContactViewModel
@{
ViewBag.Title = "Contact";
}
<h2>@ViewBag.Title</h2>
<address>
<strong>@Html.LabelFor(m => m.SupportEmail):</strong> <a href="mailto:@Model.SupportEmail">@Model.SupportEmail</a><br />
<strong>@Html.LabelFor(m => m.MarketingEmail):</strong> <a href="mailto:@Model.MarketingEmail">@Model.MarketingEmail</a>
</address>
Output
Labels:
ASP.Net MVC
Thursday, September 3, 2015
ASP.Net MVC: How to get Client IP in MVC?
private string GetClientIp()
{
string ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrWhiteSpace(ip))
{
ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
return ip;
}
{
string ip = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrWhiteSpace(ip))
{
ip = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
return ip;
}
Labels:
ASP.Net MVC
Tuesday, June 23, 2015
Using Moq and Unity together for testing
Moq lets you generate class (code) with prescribed behavior.
- Moq needs an interface
- Moq api is used to set the behavior of the generated class
Unity lets you resolve an interface to a concrete implementation.
- Register an interface with the desired concrete implementation
- The concrete implementation can be an instance of class generated by Moq for testing purposes
- In production, the interface is configured to resolve to real implementation classes
ASP.Net MVC: Using Unity IOC with MVC
1. Install Unity using Nuget
Unity bootstrapper for ASP.NET MVC(This will install all dependencies as well)
2. MVC Unity adds the following files in App_Start
UnityMvcActivator.cs - Provides the bootstrapping for integrating Unity with ASP.NET MVC. The Start() and Shutdown() methods are automatically called when MVC application starts and stops (uses WebActivatorEx to do this automatically).UnityConfig.cs - This is where you register the type mappings.
The registration is done in RegisterTypes() method. It can be done with code here or can be loaded from web.config.
Friday, May 1, 2015
Object caching in .Net with MemoryCache class
.Net 4.0 implements MemoryCache class to facilitate caching of frequently used data in any application built with .Net.
Assembly Reference: System.Runtime.Caching.dll
// using the default instance of MemoryCache in this example
// default cache is Global to the application
ObjectCache _defaultCache = MemoryCache.Default;
// Alternatively, we can create and use custom instance of MemoryCache
// const String CUSTOM_CACHE_NAME = "MyCache";
// ObjectCache customCache = new MemoryCache(CUSTOM_CACHE_NAME);
// eviction and expiration details for a specific cache entry.
CacheItemPolicy policy = new CacheItemPolicy()
{
// used to determine whether to evict a cache entry
// Priority = CacheItemPriority.NotRemovable,
Priority = CacheItemPriority.Default,
// whether a cache entry should be evicted if it has not been accessed in a given span of time.
SlidingExpiration = TimeSpan.FromMinutes(30),
// Other options
// indicates whether a cache entry should be evicted after a specified duration.
// AbsoluteExpiration = DateTimeOffset.Now.AddHours(1),
// a collection of ChangeMonitor objects that are associated with a cache entry.
// ChangeMonitors = ...
// a reference to a CacheEntryRemovedCallback delegate that is called after an entry is removed from the cache.
// RemovedCallback = ...
// a reference to a CacheEntryUpdateCallback delegate that is called before a cache entry is removed from the cache
// UpdateCallback = ...
};
// an individual entry in the cache
CacheItem item = new CacheItem(
key: Guid.NewGuid().ToString(),
value: DateTime.UtcNow
);
// true if insertion succeeded, or false if there is an already an entry in the cache that has the same key as item
var insertionSucceededBecauseNoneExistedBefore = _defaultCache.Add(item, policy);
// If a cache entry with the same key exists, the existing cache entry; otherwise, null.
var existingItemIfAnyOrNullIfNoneExistedBefore = _defaultCache.AddOrGetExisting(item, policy);
// the Set method always puts a cache value in the cache, regardless whether an entry already exists that has the same key
_defaultCache.Set(item, policy);
// A reference to the cache entry identified by key if the entry exists; otherwise, null.
var cachedItemIfAny = _defaultCache.GetCacheItem(item.Key);
// iterate through all cached items
StringBuilder sb = new StringBuilder();
foreach(var item in _defaultCache)
{
sb.AppendLine(item.Key + "= " + item.Value);
}
Assembly Reference: System.Runtime.Caching.dll
// using the default instance of MemoryCache in this example
// default cache is Global to the application
ObjectCache _defaultCache = MemoryCache.Default;
// Alternatively, we can create and use custom instance of MemoryCache
// const String CUSTOM_CACHE_NAME = "MyCache";
// ObjectCache customCache = new MemoryCache(CUSTOM_CACHE_NAME);
// eviction and expiration details for a specific cache entry.
CacheItemPolicy policy = new CacheItemPolicy()
{
// used to determine whether to evict a cache entry
// Priority = CacheItemPriority.NotRemovable,
Priority = CacheItemPriority.Default,
// whether a cache entry should be evicted if it has not been accessed in a given span of time.
SlidingExpiration = TimeSpan.FromMinutes(30),
// Other options
// indicates whether a cache entry should be evicted after a specified duration.
// AbsoluteExpiration = DateTimeOffset.Now.AddHours(1),
// a collection of ChangeMonitor objects that are associated with a cache entry.
// ChangeMonitors = ...
// a reference to a CacheEntryRemovedCallback delegate that is called after an entry is removed from the cache.
// RemovedCallback = ...
// a reference to a CacheEntryUpdateCallback delegate that is called before a cache entry is removed from the cache
// UpdateCallback = ...
};
// an individual entry in the cache
CacheItem item = new CacheItem(
key: Guid.NewGuid().ToString(),
value: DateTime.UtcNow
);
// true if insertion succeeded, or false if there is an already an entry in the cache that has the same key as item
var insertionSucceededBecauseNoneExistedBefore = _defaultCache.Add(item, policy);
// If a cache entry with the same key exists, the existing cache entry; otherwise, null.
var existingItemIfAnyOrNullIfNoneExistedBefore = _defaultCache.AddOrGetExisting(item, policy);
// the Set method always puts a cache value in the cache, regardless whether an entry already exists that has the same key
_defaultCache.Set(item, policy);
// A reference to the cache entry identified by key if the entry exists; otherwise, null.
var cachedItemIfAny = _defaultCache.GetCacheItem(item.Key);
// iterate through all cached items
StringBuilder sb = new StringBuilder();
foreach(var item in _defaultCache)
{
sb.AppendLine(item.Key + "= " + item.Value);
}
Labels:
ASP.Net MVC,
C#,
WPF
Monday, April 6, 2015
ASP.Net MVC: Implementing security for ASP.NET Web API application
Traditionally we use Forms Authentication / Form Authentication Token (Web.config). Redirects to login page; not very conducive for developing a GUI-less service layer.
The following are some possible extension points for securing an ASP.NET Web API application.
Implement custom authentication/authorization logic in the following extension points. We can still use the Form Authentication Token to save the credentials in a cookie and set the thread principal.
The following are some possible extension points for securing an ASP.NET Web API application.
Implement custom authentication/authorization logic in the following extension points. We can still use the Form Authentication Token to save the credentials in a cookie and set the thread principal.
- Implement and register an IIS IHttpModule (Runs before message handlers, and filters).
- Use Message Handlers run by the ApiController.ExecuteAsync. Implement and register a DelegatingHandler-derived class (Runs before Filters).
- Use Filters such as Authorize[] (method, controller, or global scope). We can derive from AuthorizeAttribute class to implement custom logic.
Saturday, April 19, 2014
Web Dev: Big 5 Security Measures for your Web Applications
1. Use SSL
Encryption of data in transitIf your site serves up private information, use SSL.
Use SSL, not just for the login page of your website but throughout the website. Typically, authentication credentials are stored as HTTP Cookies that are transmitted with every HTTP request. It makes no sense to grant these authentication cookies securely and later transport them insecurely for all the hackers to see (by using Network sniffers).
Use of SSL is the easiest security measure you can take. The effectiveness of the rest of the security measures described below, directly or indirectly, depend upon communicating website data over a secure communication channel.
Be sure that all security updates have been applied to your Web server. For example, if you are using OpenSSL you should close the Heartbleed Virus loophole. See: https://www.openssl.org/news/secadv_20140407.txt
Be sure that all security updates have been applied to your Web server. For example, if you are using OpenSSL you should close the Heartbleed Virus loophole. See: https://www.openssl.org/news/secadv_20140407.txt
2. Guard against SQL Injection Attacks
Execution of malicious SQL statements against the databaseIf your code forms SQL queries dynamically by directly concatenating values entered by the user, your application may be vulnerable to SQL injection attacks.
Let's say you allow users to lookup whether they are already registered on your website by entering their email address.
Behind the scenes, your code forms the following SQL query.
string sqlUserExists = "SELECT * FROM RegisteredUsers WHERE EmailAddress='" + userEnteredAddress + "'";
If the user enters, someone@xyz.com for userEnteredAddress, you get the following SQL query.
SELECT * FROM RegisteredUsers WHERE EmailAddress='someone@xyz.com';
So far, so good. But what if the user enters the following text for userEnteredAddress:
badguy@xyz.com';delete from RegisteredUsers --
The corresponding dynamic SQL becomes the following statement that deletes all users from the RegisteredUsers table.
SELECT * FROM RegisteredUsers WHERE EmailAddress='badguy@xyz.com';delete from RegisteredUsers --';
Mitigations
- Clean the user entered values that you use in dynamic SQL (for example, using RegEx). This is not the best way to guard against SQL injection attacks since the your code is responsible for cleaning up values everywhere in the code and will likely miss certain loopholes.
- Use Parameterized Queries (see SqlCommand.Parameters)
- Use Stored Procedures
- Use an ORM tool
3. Guard Against Cross Site Scripting (XSS)
A malicious script is executed from victim's browser to steal sensitive information or to cause harm to other sites using victim's browserModern websites use client side scripts (such as JavaScript) to enhance user experience. In an XSS attack, these scripts are manipulated to do malicious things such as alter DOM elements of the web page, send sensitive information to hacker sites, and to steal authentication credentials. There are several ways a hacker injects malicious scripts.
I. Passes malicious script as part of the query string. Many web applications directly use the contents of the query string to generate Web forms HTML and returns them as part of Web pages. If the contents the query string contain valid (and malicious) HTML tags and scripts, they are returned back to the Browser as part of the form and executed causing a security breach. This is an example of a reflected malicious script.
II. Injects malicious scripts into the database that returns information to the user's Web browser (see SQL injection attack description above). For example, a malicious script is inserted into one of the database columns of an entity. When that entity is displayed in user's Web browser, the malicious script is executed. This is an example of a persistent malicious script.
III. Enters input values that contain malicious script which in turn is unsafely processed by our client-side scripts. For example, if our site shows an alert by echoing values entered by the user or by adding DOM elements with values obtained after parsing JSON data (with JavaScript or jQuery), we are susceptible to such attacks. Instead of entering plain text script, a hacker may enter an encoded string to further confuse our scripts.
Mitigations
- Clean data before processing or storing it. AntiXss Sanitizer is a library that provides such capabilities (Sanitizer.GetSafeHtml() and Sanitizer.GetSafeHtmlFragement()). Specify UTF-8 encoding in web.config. That way, the hacker cannot override the text encoding and the sanitizing rules are fully enforced.
- When manipulating DOM, use safe methods to set values. For example, use setAttribute to set an attribute of an element instead of directly manipulating the html() of an element.
- Remember, not all scripts are present in <script> tags. A script may be entered as part of an HTML tag (<img onClick="alert(input)"/>). Avoid such scripts if you can (for example, use jQuery instead to add click handlers; that way the scripts will be under <script/> tags and will be easier to audit).
- In ASP.NET, enable <system.web><httpRuntime requestValidationMode="2.0" /></system.web>. This instructs ASP.NET to examine input from the browser for dangerous values.
- Use safe methods to output values of a variables to a Web page. For example, in MVC use @dataVar to safely output the value of a variable to a Web page. Micrsoft.Security.Application.Encoder.HtmlEncode(input) and Json.Encode(model) are also available to encode input that contains HTML/JavaScript.
4. Guard Against Cross Site Request Forgery (CSRF)
A malicious request is executed from victim's browser using victim's credentialsHacker uses victim's authentication credentials from victim's own browser to steal information. Here's how it works.
- Victim visits and logs into their bank site.
- Without logging out, the victim knowingly or unknowingly invokes script from a malicious site (lured by an image or any link in email, or by navigating to a link on a malicious website).
- Since the victim is still logged into their bank site, the malicious code (usually a script disguised as a link to image) performs inappropriate actions on victim's bank website usually by making a background AJAX call.
Mitigations
- Use HTTP GET exclusively for retrieving information (i.e. no data updates should ever occur as a result of an HTTP GET).
- Use HTTP POST/PUT/DELETE for updates.
- For an ASP.NET Web Form, add Session.SessionID to Viewstate. Viewstate is validated by ASP.NET and is difficult to forge by the hacker.
- For ASP.NET MVC applications, use @Html.AntiForgeryToken() for each HTML form. Apply [ValidateAntiForgeryToken()] to the POST controller method.
5. Secure data at rest
Encrypt data that is stored in file system, and databases
Say a hacker gains access to the file system or database of your Web application. The hacker can do a lot of damage with the data stored by Web application.
Mitigations
- Whenever possible encrypt and then store sensitive data. This puts another layer of protection between your Web application and the hacker.
- Always store hash of passwords (instead of plain text representation). Furthermore, use a salt when creating a hash. The use of salt will thwart against a Dictionary attack.
Monday, September 16, 2013
ASP.Net MVC: Internationalization (i18n) and Localization (i10n) in MVC
Internationalization (i18n) and Localization (i10n) are collectively know as Globalization.
DateTime.Now.ToString(); // how is date displayed, month first, day first, etc.
date.ToShortDateString(); // format date appropriate for the culture
// what currency symbol is shows; what is 1000s separator
// decimal separator; 10.00 E (in euros)
amount.ToString(“c”);
ErrorMessageResourceName=”UserNameRequiredError”]
public string username {get; set;}
2. Create MyResources.resx
Greeting: Welcome
3. Change access modifier to public from Internal so that the Razor views can use it since Razor views are compiled to a different assembly.
4. Add MyResources.fr.resx
Greeting: Bonjour!
For the localized resource, no code generation. Only done for the base resource file.
5. Modify view to use the resources
<h1>@<namespace>.MyResources.Greeting</h2>
This will load the correct string based on appropriate language accept header.
We can also create resources within the View subfolder and use in the View.
// Adjust cache settings to vary by language
[OutputCache ... VarByHeader=”Accept-Language”)]
ViewBag.Message = MyResources.Greeting;
ASP.Net Culture
Every executing .Net thread has two important properties.- Thread.Culture
- Thread.CurrentUICulture
Thread.Culture
Impacts formatting of dates and numbers. For example:DateTime.Now.ToString(); // how is date displayed, month first, day first, etc.
date.ToShortDateString(); // format date appropriate for the culture
// what currency symbol is shows; what is 1000s separator
// decimal separator; 10.00 E (in euros)
amount.ToString(“c”);
Thread.CurrentUICulture
- Impacts loading of resources, such as strings
- Use Resources.resx to Localize the strings being displayed. For example, Strings.resx will store default resources.
- Resx files can store localized text and binary assets
- Create a Resource for each language you wish to support. For example, String.es.resx will store resource for Spanish culture
- Resource Loader loads the current resources for the culture
- In Visual Studio, set the BuildAction to embedded resource
- Visual Studio generates strongly-typed classes for Resource access
- Resources.Greeting returns culture specific string; falls back to base resources if no culture specific resource is present
Setting Culture in ASP.NET using HTTP headers
- Default language of the browser is passed in the accept-language header
- To turn on, refer to the <globalization> section of web.config
<system.web>
<globalization culture=”auto” uiCulture=”auto” />
</system.web>
Testing formatting based on accept-language header
- Go to Settings for Internet Explorer
- Internet Options
- Under appearance press [Languages]
- Pick a language
Manually Setting Culture in ASP.NET
- For example, user can select the language on the log in page
- Use CultureInfo::DefaultThreadCurrentCulture to set desired culture before using formatting classes and methods
Referencing resources in MVC
In Data Model using Data Annotation
[Required(ErrorMessageResourceType=type(<namespace>.MyResources),ErrorMessageResourceName=”UserNameRequiredError”]
public string username {get; set;}
In Razor View
1. Create Resource files. The resource files can be created in the same Web project, a Separate Library, or a separte folder in the Web project.2. Create MyResources.resx
Greeting: Welcome
3. Change access modifier to public from Internal so that the Razor views can use it since Razor views are compiled to a different assembly.
4. Add MyResources.fr.resx
Greeting: Bonjour!
For the localized resource, no code generation. Only done for the base resource file.
5. Modify view to use the resources
<h1>@<namespace>.MyResources.Greeting</h2>
This will load the correct string based on appropriate language accept header.
We can also create resources within the View subfolder and use in the View.
In Cached controller action
// Returns language-specific CACHED data// Adjust cache settings to vary by language
[OutputCache ... VarByHeader=”Accept-Language”)]
Controller
Can also use as follows in controllerViewBag.Message = MyResources.Greeting;
Labels:
ASP.Net MVC
Friday, September 13, 2013
ASP.Net MVC: Cross Site Request Forgery - CSRF
How does it happen?
- User logs in
- Our site sends back an authentication cookie
- On every subsequent request, the user’s browser will send the cookie back to our server and the server knows the user's agent (browser) is authenticated
Browser ---> Authenticate me ---> Server
Server --> OK, take this authentication cookie and supply to me on subsequent requests --> Browser
So far so good
- User goes to another site or tricked into picking HTML from another malicious site. Links in suspicious emails are a common way by which users are tricked.
- The malicious link puts up a page/form in the user's web browser that points to our site and posts a form with bad information. The form has all the inputs in the form to apply changes (recall that the user browser already has the authentication cookie previously obtained upon authentication).
- At the bottom of the malicious form, there is a script to automatically submit this form when the form POPs up.
- < form action=>..
- <div>
- < input...>
- </div>
- <script type=”text/javascript”>
- document.getElementById(“theForm”.submit());
- </script>
- The malicious request or form works against our Server because the browser has been previously authenticated
- Result: The user has just inadvertently submitted data on behalf of the malicious site
It is not enough to be authenticated
- In MVC, we use the Authorize attribute on HttpGets and HttpPosts to authenticate the user before the controller action proceeds any further
- GETs should not be used to update information on the Server; only POSTs should update information
- Our server should not only make sure the POST request is from an authenticated browser but it must also make sure the form being posted originated from our server.
- Therefore, we must check that the information being submitted is from a FORM our Server provided to the browser
Use the Html Anti-forgery token in MVC Forms
- An Html helper adds hidden input to the form with a value unique to user’s browsing session
- A matching value (anti-forgery token) is sent as a cookie to user’s browser
- Malicious user is not able to manipulate cookies for your server domain
- The Anti-forgery token will comes back during authenticated postback
// Razor code
@using (Html.BeginForm())
{
HtmlHelper.AntiforgeryToken();
@Html.ValidationSummary(true);
...
}
- To enforce the anti-forgery token, an ValidateAntiForgeryToken attribute must be applied to POST controller action
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken] // make sure form value and cookie values match
// Valid only for POST verb
public ActionResult Edit(Review review)
{
...
}
- Now the malicious popup will get an error from ASP.Net: A required anti-forgery token was not supplied or was invalid.
Labels:
ASP.Net MVC
Thursday, July 5, 2012
Js Library: Client-side template to output data - jQuery Templates
No included in MVC. Can use NuGet tools to get it. Right click on project. Look for jQuery templates.
Add Library Package Reference. Search for jquery template (jquery.tmpl.js)
In Script tag to include: jQuery-tmpl-min.js
Only jquery template plug-in will use the following. Browsers will ignore because fof type
// jQuery template with data which has Name, City and Country property
<script id=”searchTemplate” type=”text/x-jquery-tmpl”>
<tr>
<td>${Name}</td>
<td>${City}, ${Country}</td>
</tr>
</script>
Steps
1. Use a standard form tag. Using jquery instead of using jquery helpers.
<form method=”get”
action=”@Url.Action(“JsonSearch”, “Home”)”
id=”searchForm”>
<input type=”text” name=”q” data-autocomplete=”@Url.Action(“QuickSearch”, “Home”)”
<input type=”submit” value=”Search”/>
</form>
public ActionResult JsonSearch(string q)
{
var restaurants = _db.Restaurants
.Where( r=> r.Name.Contains(q) || String.IsNullOrEmpty(q))
.Take(10)
.Select (r => new
{
r.Name, r.Address.City, r.Address.Country
});
return Json(restaurants, JsonRequestBehavior.AllowGet);
}
2. OnReady hookup the Submit event of the Form
$(document).ready(function() {
... // autocomplete
... // date picker
$(“#searchForm”).submit(function() {
$.getJSON($(this).attr(“action”), // the url to get JSON from
$(this).serialize(), /// serialize the values posted i.e. q=yellow
function (data) { // what to do with the response
var result = $(“#searchTemplate”).tmpl(data); // use tmpl function to find the template
$(“#searchResults”).empty().append(result);
}
return false;
}
Labels:
ASP.Net MVC
AutoComplete using jQuery UI
jQuery UI is a plug-in for jQuery
To use a different theme, ensure the CSS and image files are present in the Content directory
To use jquery UI:
1. Add link in CSS
<link href=”@Url.Content(“~/Content/themes/base/jquery-ui.css)” type=../>
additional theme go into Content/themes folder
This link can be changed based on user’s preferred theme
2. At the bottom of page add minified version of jQueryUI
..
@Content.Script(“jquery-ui.min.js”, Url)
@RenderSection(“scripts”, false)
To implement AutoComplete
1) Add a new js file to Contents\Scripts folder
2) Add the link to the script at the bottom
3) In the script editor, drag the following to the file editor:
/// reference path=”jquery-1.4.4-vsdoc.js” />
/// reference path=”jquery-ui.js” />
Tells VS that we are using these and VS provide intellisense. Does not include the scripts.
$(document).ready(function() // once DOM model is loaded
{
// identify the element that needs autocomplete behavior
// and how to the get the data for the autocomplete
$(“”).autocomplete();
}
)
In the html, add a class attribute to the element:
<input type=”text” name=”q” class=”autocomplete” /> // q is fashionable name to use for search query
$(document).ready(function() // once DOM model is loaded
{
// identify the element that needs autocomplete behavior
// and how to the get the data for the autocomplete using the class name
$(“autocomplete”).autocomplete();
}
)
can also use data- attrib
<input type=”text” name=”q” data-autoComplete=”@Url.ACtion(“QuickSearch, Home” />
$(document).ready(function() // once DOM model is loaded
{
// identify the element that needs autocomplete behavior
// and how to the get the data for the autocomplete using the class name
// wire-up autocomplete behavior each input that has data-autocomplete
// attribute using the Url provided in data-autocomplete
$(“:input[data-autocomplete]”).each(
function() {
$(this).autocomplete( { source : $(this).attr(“data-autocomplete”)});
});
Now need Controller action that will respond to controller action:
public ActionResult QuickSearch(string term)
{
var restaurants = _db.Restaurants
.Where (r => r.Name.Contains(term))
.Take(10)
.Select (r => new {label = r.Name });
return Json(restaurants, JsonRequestBehavior.AllowGet);
}
Autocomplete doc says it will send a term parameter
Autocomplete expects data in Json format
Further, it expects “label”, name pairs
Labels:
ASP.Net MVC
Monday, July 2, 2012
Razor - Partial Views
HTML/C# code in a file for reuse in other views. Helps avoid duplication of markup.
Prefix the partial view with an underscore as a convention.
Can still use the strongly typed view.
If you have already generated tags as normal view, can leave scaffold template empty and copy and paste the tags in the partial view.
[x] Create as a partial view (=> does not set the title)
@model xxx.Models.xxx // strongly-typed
Razor code here that references the Model directly
<div class=”review”>
<h4>@Model.Restaurant.Name</h4>
...
To render partial view in a normal View.
@foreach (var item in Model)
{
// Render portion of the model in a specific view
@Html.Partial(“_partialviewName”, item) // item becomes the Model for the partial view
}
If partial view is placed in Views folder, it is only available to views in that folder.
If in Shared folder, can use it anywhere in the app.
Another use of partial view... delegate work to some other controller.
Rendering partial view that does not really have a model associated with it. Executed for different views; those views will be using different models.
For example, say we want to place output of some (sub-)controller in an area of the main view.
// 1) create a controller action that returns the partial view
public ActionResult BestReview()
{
var model = _db.Reviews.FindTheBest();
return PartialView(“_Review”, model);
}
// 2) Invoke the sub-co0ntr
<div id=”main>
@RenderBody()
<div id=”footer”>
// we may want to show this information on every page
@Html.Action(“BestReview”, “Reviews”)
// does not require any specify type of model; the controller generates everything;
// it still takes advantage of strongly-typed view
// this was specified in the View for copyright; separate from BestReview
@RenderSection(“Footer”, false)
</div>
</div>
</div>
To make the following not accessible from Browser:
[ChildActionOnly]
public ActionResult BestReview()
{
var model = _db.Reviews.FindTheBest();
return PartialView(“_Review”, model);
}
Labels:
ASP.Net MVC
Subscribe to:
Posts (Atom)






