If you want to display 2 radio buttons for a boolean property in Razor with Yes and No labels, this is how you could do it.
Create your own editor template and put it in the Shared/EditorTemplate folder.
Template code:
@model bool
@using System.Web.Mvc
@Html.RadioButtonFor(model=>model, false) No
@Html.RadioButtonFor(model => model, true) Yes
Monday, December 15, 2014
Thursday, October 23, 2014
Create Separate Dropdowns for Day, Month, Year in ASP.NET MVC
Create a structure that will hold the Month, Day and Year fields:
Create SelectListItem Date, Month and Year collections and add them to the ViewBag.
Now, in your controller method you can access the selected values as follows:
Your model class should contain the following properties;public struct DatePart { public static IEnumerable<int> DayItems { get { return Enumerable.Range(1, 31); } } public static IEnumerable<String> MonthItems { get { return new System.Globalization.DateTimeFormatInfo().MonthNames; } } public static IEnumerable<int> YearItems { get { return Enumerable.Range(DateTime.Now.Year - 30, 30 + 1); } } }
public int Day { get; set; } public int Month { get; set; } public int Year { get; set; }
Create SelectListItem Date, Month and Year collections and add them to the ViewBag.
In the view, create dropdowns and populate them with collections in the ViewBag.ViewBag.Days = DatePart.DayItems.Select(d => new SelectListItem { Text = d.ToString() }); ViewBag.Months = DatePart.MonthItems.Select((m, i) => new SelectListItem { Value = (i + 1).ToString(), Text = m }); ViewBag.Years = DatePart.YearItems.Select(y => new SelectListItem { Text = y.ToString() });
It is important that the select element names match the property names in the model.@Html.DropDownList("Day", (IEnumerable<SelectListItem>) ViewBag.Days) @Html.DropDownList("Month", (IEnumerable<SelectListItem>) ViewBag.Months) @Html.DropDownList("Year", (IEnumerable<SelectListItem>) ViewBag.Years)
Now, in your controller method you can access the selected values as follows:
var selectedTime = new DateTime(model.Year, model.Month, model.Day);
Thursday, February 27, 2014
Replace foreach with Extension Methods and Lambda Expressions
I suppose many of us use the foreach statement very often in our code. I'll show you how to replace simple foreach statements with new lambda expressions.
Suppose you want to create a List < string> of names of files residing in a directory. This is how you could do it.
Set up an array of FileInfo objects:
Create a string type List:
That's one line instead of 3. But we still want a List <string> object to be used later in the code. We need to use the Enumerable.ToList <TSource> method to cast to a List. This is how we do it:
This way you use one line of code instead of 4.
Modify Elements in a Collection
Use the Select method to modify elements in a collection. The important part is you need to return each element;
An example follows:
var plans = query.AsEnumerable().Select(it =>
{
it.PlanYears = Enumerable.Range(it.Plan.StartDate.Year, (DateTime.Now.Year - it.Plan.StartDate.Year) + 1);
return it;
});
How to get an ordinal position of an item in the list.
Example:
Which equivalent extension method can we use to achieve the same result? We need to use the Where extension method of the IEnumerable <T> interface first, and then append the earlier Select method to the statement:
-->
IncomeSourceList.FindAll(item => item.ItemSourceType == SourceType.PERM).ForEach(
item => Debug.WriteLine(item.ItemSourceType)
);
This code selects only those collection items whose ItemSourceType equals to PERM type, and then loops through the result.
Query operator ToList() forces immediate query evaluation.
What if you have a method that loops through an array and returns a bool type depending on some condition inside the loop. Can we use query operators instead? It is slightly more difficult but still possible.
Suppose you have the following methods that compares each character in a string array to each character in another string array and returns false when a character in the second array is not found in the first array:
To emulate similar statements, first we need to find the first non-matching character:
We use the FirstOrDefault operator instead of First because otherwise we may have "Sequence contains no matching element" error if the expression does not returns any characters.
Now we can return a bool value depending on the result of the previous statement:
For sheer fun you can rewrite those two statements as follows:
Example:
Let's say we have a Sales table with the following fields: Rep, SalesDate, RepEmail, etc. We want to know how many sales each Rep made each month.
First, let's build a query that counts the total number of sales per Rep:
This query would translate into the following sql statement:
To group the result further by month, we would use the following query:
Any
To find out if an element exists in a collection, use the extension method Any:
Some other posts you might find interesting:
Suppose you want to create a List < string> of names of files residing in a directory. This is how you could do it.
Set up an array of FileInfo objects:
string filePath = @"C:\Temp";
DirectoryInfo dInfo = new DirectoryInfo(filePath);
FileInfo[] fileInfoArray = dInfo.GetFiles();
Create a string type List:
List<string> fileList = new List<string>();
foreach (FileInfo fi in fileInfoArray)
{
fileList.Add(fi.Name);
}
Select
Using lambda expressions and the Select extension method it is possible to re-write the last 3 lines as follows:
var files = fileInfoArray.Select(fi => fi.Name);
That's one line instead of 3. But we still want a List <string> object to be used later in the code. We need to use the Enumerable.ToList <TSource> method to cast to a List. This is how we do it:
List<string> fileList2 = fileInfoArray.Select(fi => fi.Name).ToList ();
This way you use one line of code instead of 4.
Modify Elements in a Collection
Use the Select method to modify elements in a collection. The important part is you need to return each element;
An example follows:
var plans = query.AsEnumerable().Select(it =>
{
it.PlanYears = Enumerable.Range(it.Plan.StartDate.Year, (DateTime.Now.Year - it.Plan.StartDate.Year) + 1);
return it;
});
How to get an ordinal position of an item in the list.
Example:
var mm = new System.Globalization.DateTimeFormatInfo().MonthNames.Select( (a, i) => new { Item = a, Position = i });
Where
Now, what if we add only those file names to the List that meet certain criteria, e.g:
foreach (FileInfo fi in fileInfoArray)
{
if (fi.Length > 10000000)
{
largeFiles.Add(fi.Name);
}
}
Which equivalent extension method can we use to achieve the same result? We need to use the Where extension method of the IEnumerable <T> interface first, and then append the earlier Select method to the statement:
var varLargeFiles = fileInfoArray.Where (fi => fi.Length > 1000000).Select(fi=>fi.Name);
FindAll
If you need to filter your collection and iterate through the result, use the FindAll extension:IncomeSourceList.FindAll(item => item.ItemSourceType == SourceType.PERM).ForEach(
item => Debug.WriteLine(item.ItemSourceType)
);
This code selects only those collection items whose ItemSourceType equals to PERM type, and then loops through the result.
LINQ
Now, to complete the example, I'll show the way to obtain a similar list using the LINQ:
var q = from fi in fileInfoArray
where fi.Length > 1000000
select fi.Name;
List<string> largeFiles2 = q.ToList();
Query operator ToList() forces immediate query evaluation.
Boolean Methods
What if you have a method that loops through an array and returns a bool type depending on some condition inside the loop. Can we use query operators instead? It is slightly more difficult but still possible.
Suppose you have the following methods that compares each character in a string array to each character in another string array and returns false when a character in the second array is not found in the first array:
public static bool IsAnagram(string word, string input)
{
char[] inputArray = input.ToCharArray();
foreach (char ch in word.ToCharArray())
{
if (!inputArray.Contains(ch))
return false;
}
return true;
}
To emulate similar statements, first we need to find the first non-matching character:
char c = word.ToCharArray().FirstOrDefault (x => !inputArray.Contains(x));
Now we can return a bool value depending on the result of the previous statement:
return (c != 0) ? false: true;
For sheer fun you can rewrite those two statements as follows:
return (word.ToCharArray().FirstOrDefault(x => !inputArray.Contains(x))) == 0;
Grouping
Grouping allows us to group the result into distinct groups using a field or several fields as group criteria. Each group will have a key property that you can use to refer to the field(s) grouped on.Example:
Let's say we have a Sales table with the following fields: Rep, SalesDate, RepEmail, etc. We want to know how many sales each Rep made each month.
First, let's build a query that counts the total number of sales per Rep:
from s in Sales group s by s.Rep into gr select new { Name = gr.Key, Count = gr.Count() }
This query would translate into the following sql statement:
select Rep as Name, Count(*) from Sales Group By Rep
To group the result further by month, we would use the following query:
from s in Sales group s by new {s.Rep, s.SalesDate.Month} into gr select new { Name = gr.Key.Rep, SalesMonth = gr.Key.Month, Count = gr.Count() }
Sorting
This does not really belong in this post, however, here is a quick way to sort a list of objects. Your object could be similar to this one:
class MyObject{ public string Symbol {get;set;} public double Value {get;set;} } myList.Sort((a, b) => a.Symbol.CompareTo(b.Symbol));
Any
To find out if an element exists in a collection, use the extension method Any:
if(userRoles.Any(role=> role.Equals("Admin")))
...
Some other posts you might find interesting:
Query Operator First
Easy Syntax to Print List Elements
Wednesday, September 4, 2013
Deploy ASP MVC on IIS 6
This post just complements information already available online.
There are certain steps you need to do first before your ASP MVC application can run in IIS 6.
In the Properties screen, on the Directory tab click Configuration.
On the Mappings tab, click Insert to insert a wildcard application map:
Browse to the location of the aspnet_isapi.dll file. Make sure that Verify that file exists check-box is clear.
Click OK to save your changes. That should be enough provided you have all the required dll files in the bin folder.
There are certain steps you need to do first before your ASP MVC application can run in IIS 6.
In the Properties screen, on the Directory tab click Configuration.
On the Mappings tab, click Insert to insert a wildcard application map:
Browse to the location of the aspnet_isapi.dll file. Make sure that Verify that file exists check-box is clear.
Click OK to save your changes. That should be enough provided you have all the required dll files in the bin folder.
Thursday, July 18, 2013
Copy Property Values
If you have 2 objects that do not inherit from each other but have similar properties, here is a function you can use to copy property values from one object to the other:
public static void CopyIdenticalProperties (this object source, object dest)
{
var plist = from prop in source.GetType().GetProperties()
where prop.CanRead && prop.CanWrite
select prop;
foreach (PropertyInfo prop in plist)
{
var destProp = dest.GetType().GetProperty(prop.Name);
if (destProp != null)
{
destProp.SetValue(dest, prop.GetValue(source, null), null);
}
}
}
Wednesday, June 12, 2013
Format Phone Number
This is how you could format a phone number using a period as a separator:
String.Format("{0:###\\.###\\.####}", 1234567890);
The resulting string will look as follows: 123.456.7890.
String.Format("{0:###\\.###\\.####}", 1234567890);
The resulting string will look as follows: 123.456.7890.
Wednesday, November 28, 2012
Update WCF Service Site References
If you have a problem updating dll files in the bin folder of your Web Site deployment project, the following method may work: delete all dll files in your bin folder, and then add a reference to you Service project. All the other required dll files will be added automatically.
Thursday, May 31, 2012
Regex for Month Number
This is the regular expressions pattern I use to test whether string characters represent a month number (from 01 to 12):
(0[1-9]|1[0-2])
The expression part inside the brackets is broken into 2 possible parts divided by a vertical bar (or pipe symbol): 0[1-9] or 1[0-2].
If a string matches any of the 2 parts it is true.
The first one says that the 2-character string has to start with 0 and end with any number in the range from 1 to 9, e.g. 01, 02, 09
The second part matches any 2-character string that starts with 1 and ends with 0, 1 or 2, i.e. 10, 11, or 12
(0[1-9]|1[0-2])
The expression part inside the brackets is broken into 2 possible parts divided by a vertical bar (or pipe symbol): 0[1-9] or 1[0-2].
If a string matches any of the 2 parts it is true.
The first one says that the 2-character string has to start with 0 and end with any number in the range from 1 to 9, e.g. 01, 02, 09
The second part matches any 2-character string that starts with 1 and ends with 0, 1 or 2, i.e. 10, 11, or 12
Monday, March 12, 2012
Delete Contents of IsolatedStorageFile
The easiest way to delete contents of an IsolatedStorageFile is to open it in the Truncate mode:
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForAssembly();
IsolatedStorageFileStream isoFile = new IsolatedStorageFileStream(myFileName, FileMode.Truncate, isoStore);
According to the MSDN , if a file is opened in the Truncate mode its size should be 0 bytes.
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForAssembly();
IsolatedStorageFileStream isoFile = new IsolatedStorageFileStream(myFileName, FileMode.Truncate, isoStore);
According to the MSDN , if a file is opened in the Truncate mode its size should be 0 bytes.
Friday, December 2, 2011
Delete ScriptManager History
Well, I have not found a way to clear ScriptManager history proper, but the workaround is to use the AddHistoryPoint method and set the value of your property to "0":
ScriptManager1.AddHistoryPoint("myKey", "0");
ScriptManager1.AddHistoryPoint("myKey", "0");
Tuesday, October 25, 2011
Check if GridView Column Exists
If you have a DataRowView you can use the following extension method to check if a GridView column exists:
public static bool ColumnExists( this DataRowView rowData, string fldToCheck)
{
return rowData.Row.Table.Columns.Contains(fldToCheck);
}
Normally, you would use it on RowDataBound event, e.g:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
DataRowView rowData = e.Row.DataItem as DataRowView;
string fldToCheck = "MyFieldName";
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (rowData.ColumnExists(fldToCheck) ...
Related posts:
Find GridView Column Index
Set DataRow Values and Other ASP.NET GridView Tips
public static bool ColumnExists( this DataRowView rowData, string fldToCheck)
{
return rowData.Row.Table.Columns.Contains(fldToCheck);
}
Normally, you would use it on RowDataBound event, e.g:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
DataRowView rowData = e.Row.DataItem as DataRowView;
string fldToCheck = "MyFieldName";
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (rowData.ColumnExists(fldToCheck) ...
Related posts:
Find GridView Column Index
Set DataRow Values and Other ASP.NET GridView Tips
Monday, October 17, 2011
Modify Query String
If you build a hyperlink on a web page dynamically, sometimes you may need to append or modify an existing query string.
To modify a url with an existing query string, first grab the AbsoluteUrl property:
string path = Request.Url.AbsolutePath ;
This will give you a url wihout the query string portion.
If you need to reuse an existing portion of the query string, you have to get it yourself, e.g:
string key = Request.QueryString["key"];
string path = Request.Url.AbsolutePath + "?key="+ key;
Now, you can build your url:
string url = path+ "&key2="+ myValue;
Related posts:
Add JavaScript Dynamically to ASP.NET UpdatePanel
Examine Columns in ASP.NET Dynamic Data MetaTable
Thursday, October 13, 2011
Find GridView Column Index
If you create GridView columns dynamically using the AutogenerateColumns = true feature, sometimes you need to find a column index from the column name.
I created an extension method to find a column index:
This is how you call from the RowDataBound event handler:
I created an extension method to find a column index:
public static int GetIndex(this DataRowView tableData, string fieldName) { DataColumn dc = tableData.DataView.Table.Columns[fieldName]; if (dc != null) { return dc.Ordinal; } return -1; }
This is how you call from the RowDataBound event handler:
DataRowView tableData = e.Row.DataItem as DataRowView; int pos = tableData.GetIndex("MyFieldName"); if (pos != -1){ //do your thing }
Wednesday, July 27, 2011
Thursday, March 17, 2011
Check QueryString for Null
If you need to determine whether the Request.QueryString is null and take some action depending on the result, it is not enough to check for null. QueryString is an HttpValueCollection type, so even if the Request.Url does not have a query string appended to it, the value of the collection is not going to be null. The proper way to check if the query string contains anything is to check for null and the Count property as well:
if(Request.QueryString!= null && Request.QueryString.Count>0){
//some piece of code.
}Friday, December 3, 2010
C# Delegates as Method Parameters
Let's say you have 2 methods that go through similar steps:
These 2 methods essentially do the same thing. First, they check for some condition, and if the condition evaluates to true, they call another method, set some properties, and return a string. We can use C# delegates to refactor these 2 methods into one. Here is how you do it:
Declare 2 delegates whose signature matches the methods we want to replace:
Create a method that will use the delegates:
An alternative method signature is as follows:
This way we don't have to declare delegates separately.
Now, we can call the new method, passing the methods that we called before refactoring, as parameters:
An interesting discussion of delegates can be found on the stackflow.
public string GetPrevItem()
{
if (IsValidPrevEntry())
{
string item = GetPrevString();
SetProperties();
return item;
}
else
return null;
}
public string GetNextItem()
{
if (IsValidNextEntry())
{
string item = GetNextString();
SetProperties();
return item;
}
else
return null;
}
Declare 2 delegates whose signature matches the methods we want to replace:
delegate bool IsValid();
delegate string GetItem();
private string GetMyItem(IsValid isValid, GetItem getItem)
{
if (isValid())
{
string item = getItem();
SetEventProperties();
return item;
}
else
return null;
}
private string GetNavItem(Func<bool> isValid, Func<string> getItem)
Now, we can call the new method, passing the methods that we called before refactoring, as parameters:
string strPrev = GetMyItem(IsValidPrevEntry, GetPrevString);
string strNext = GetMyItem(IsValidNextEntry, GetNextString);
Tuesday, November 16, 2010
Add JavaScript Dynamically to ASP.NET UpdatePanel
Use the following example:
What it does is attaches a JavaScript function (defined elsewhere) to each input box on the page on the key press event, and then registers it for use with a control that is inside an UpdatePanel. This could be used for user input validation. The code has been verified in IE and Firefox.
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(@" var inputs = document.getElementsByTagName('input'); for (var i = 0; i < inputs.length; i++) {
if (inputs[i].type == 'text') {
inputs[i].onkeypress = function (event) {
event = event || window.event;
return myJavaScriptFunction(event);}
event = event || window.event;
return myJavaScriptFunction(event);}
}}"
);
What it does is attaches a JavaScript function (defined elsewhere) to each input box on the page on the key press event, and then registers it for use with a control that is inside an UpdatePanel. This could be used for user input validation. The code has been verified in IE and Firefox.
Wednesday, November 10, 2010
ASP.NET GridView Subclass with Dynamic Footer Totals
A frequent requirement when using an ASP.NET GridView on a web page is to have a footer with totals for numeric columns in the GridView. Here is a GridView subclass that calculates footer totals dynamically. It requires 3 parameters:
FirstComputedColumnIndex - the for index of the first column in the data set to be computed
FirstVisbleComputedColumnIndex - for the index of the first computed column to be shown
NumberOfComputedColumns - for the number of computed columns.
Here is the class code:
The Indexer class can be nested within the GridView subclass.
The last example shows how to use the custom GridView on a ASP.NET web page:
First, use the register tag:
<%@ Register Namespace="Eric.TotalGrid" TagPrefix="x" Assembly="TotalGrid" %>
Then, use it just like any other GridView:
<x:GridView runat="server" ....
FirstComputedColumnIndex="4" FirstVisbleComputedColumnIndex="3" NumberOfComputedColumns="10" >
FirstComputedColumnIndex - the for index of the first column in the data set to be computed
FirstVisbleComputedColumnIndex - for the index of the first computed column to be shown
NumberOfComputedColumns - for the number of computed columns.
Here is the class code:
namespace Eric.TotalGrid {
public partial class GridView : System.Web.UI.WebControls.GridView
{
private Indexer footerTotals;
public int FirstComputedColumnIndex { get; set; }
public int FirstVisbleComputedColumnIndex { get; set; }
public int NumberOfComputedColumns { get; set; }
protected override void OnLoad(EventArgs e)
{
ShowFooter = true;
base.OnLoad(e);
}
protected override void OnInit(EventArgs e)
{
footerTotals = new Indexer(NumberOfComputedColumns);
InitializeComponent();
base.OnInit(e);
}
private void InitializeComponent()
{
this.RowDataBound += new GridViewRowEventHandler(this.GridView1_RowDataBound);
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
DataRowView tableData = e.Row.DataItem as DataRowView;
if (e.Row.RowType == DataControlRowType.DataRow)
{
for (int i = FirstComputedColumnIndex; i < (FirstComputedColumnIndex + NumberOfComputedColumns); i++)
{
if (tableData[i] != DBNull.Value)
{
decimal result = 0;
if (Decimal.TryParse(tableData[i].ToString(), out result))
{
footerTotals[i - FirstComputedColumnIndex] += result;
}
}
}
}
else if (e.Row.RowType == DataControlRowType.Footer)
{
for (int i = 0; i < NumberOfComputedColumns; i++)
{
if (e.Row.Cells.Count > (i + FirstVisbleComputedColumnIndex))
e.Row.Cells[i + FirstVisbleComputedColumnIndex].Text = footerTotals[i].ToString();
}
}
}
}
The key to this GridView is using an Indexer class that can be accessed like an array. Here is its listing:
}
The key to this GridView is using an Indexer class that can be accessed like an array. Here is its listing:
class Indexer
{
private int _upperLimit;
private decimal[] myArray;
public Indexer(int limit)
{
_upperLimit = limit;
myArray = new decimal[_upperLimit];
}
public decimal this[int index] // Indexer declaration
{
get
{
// Check the index limits.
if (index < 0 || index >= _upperLimit)
return 0;
else
return myArray[index];
}
set
{
if (!(index < 0 || index >= _upperLimit))
myArray[index] = value;
}
}
}
The last example shows how to use the custom GridView on a ASP.NET web page:
First, use the register tag:
<%@ Register Namespace="Eric.TotalGrid" TagPrefix="x" Assembly="TotalGrid" %>
Then, use it just like any other GridView:
<x:GridView runat="server" ....
FirstComputedColumnIndex="4" FirstVisbleComputedColumnIndex="3" NumberOfComputedColumns="10" >
Thursday, October 28, 2010
Set DataRow Values and Other ASP.NET GridView Tips
You can set DataRow values in two ways:
First, using a column name:
myDataRow["City"]= "London";
Or, using an index:
myDataRow[2] = "London";
Don't use ItemArray property to set values, it won't work.
<asp:BoundField... ControlStyle-Width="60px"/>
There are different ways to change GridViewRow appearance. The approach I like involves using the GridViewRow Style property. On RowDataBound event use this:
Did you know that you could pass data format string as a parameter to the ToString() method?
For example:
The above format string specifies 2 decimal places in a numeric value.
First, using a column name:
myDataRow["City"]= "London";
Or, using an index:
myDataRow[2] = "London";
Don't use ItemArray property to set values, it won't work.
Set Text Box Width in a GridView Bound Field:
Use ControlStyle properties:<asp:BoundField... ControlStyle-Width="60px"/>
Change GridViewRow Appearance:
There are different ways to change GridViewRow appearance. The approach I like involves using the GridViewRow Style property. On RowDataBound event use this:
if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Style.Add("color", "#999999");
e.Row.Style.Add("font-weight", "bold");
...
}
Did you know that you could pass data format string as a parameter to the ToString() method?
For example:
e.Row.Cells[1].Text = iTotal.ToString("F2")
Tuesday, October 26, 2010
Simple Linq to Object example without Casting
I found this discussion related to casting the result of a LINQ query to a static object at http://devlicio.us/blogs/derik_whittaker/archive/2008/02/22/simple-linq-to-object-example-with-casting.aspx Since it was not possible to post a comment I decided to write a blog entry on my blog.
The example given at the above page gives the following code:
I would like to note that you could rewrite the above statements using lambdas:
No "casting" is required.
The example given at the above page gives the following code:
List<Sport > sports = new List <Sport>();
sports.Add(new Sport { SportID = 1, Name = "Sport 1", Description = "Sport Desc 1" });
sports.Add(new Sport { SportID = 2, Name = "Sport 2", Description = "Sport Desc 2" });
sports.Add(new Sport { SportID = 3, Name = "Sport 3", Description = "Sport Desc 3" });
sports.Add(new Sport { SportID = 4, Name = "Sport 4", Description = "Sport Desc 4" });
sports.Add(new Sport { SportID = 5, Name = "Sport 5", Description = "Sport Desc 5" });
var query = from s in sports
where s.Name == "Sport 2"
select s;
Sport sport = (Sport)query.First();
I would like to note that you could rewrite the above statements using lambdas:
Sport sport = sports.Where(s => s.Name == "Sport 2").First();
No "casting" is required.
Subscribe to:
Posts (Atom)

