Get a string description from an enum

< 1 min read Enums can be very powerful when used appropriately, such as for populating fixed drop-down lists which almost never change

Let’s say you want to save a person’s gender in your database. You could save it as a string, but that’s very wasteful. Ideally you’d save it as tinyint, because it will never have more values, so why waste space and computing time with joins, or other solutions.
Your enum could look like this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel;

namespace Data.Enums
{
    public enum Genders : byte
    {
        [DescriptionAttribute("No Answer")]
        NoAnswer = 0,
        [DescriptionAttribute("Male")]
        Male = 1,
        [DescriptionAttribute("Female")]
        Female = 2
    }
}

Log and email errors in MVC 3

3 min read

void Application_Error(object sender, EventArgs e)
{
    ErrorTracking.TrackingInfo info = new ErrorTracking.TrackingInfo();
    info.ErrorPath = "http://" + Request.ServerVariables["HTTP_HOST"] + Request.Path;
    info.RawUrl = Request.RawUrl;
    string strError = "Error in: http://" + Request.ServerVariables["HTTP_HOST"] + Request.Path +
    "nUrl: " + Request.RawUrl + "nn";
    try
    {
        // Get the exception object for the last error message that occured.
        Exception ErrorInfo = Server.GetLastError().GetBaseException();
        if (ErrorInfo != null)
        {
            strError += "Error Message: " + ErrorInfo.Message +
                "nError Source: " + ErrorInfo.Source +
                "nError Target Site: " + ErrorInfo.TargetSite;
            info.ErrorMessage = ErrorInfo.Message;
        }
        strError += "Error Type: " + Server.GetLastError().GetType().ToString();
        info.ErrorType = Server.GetLastError().GetType().ToString();
        if (Server.GetLastError().GetType() == typeof(HttpUnhandledException))
        {
            strError += "Source: " + (Server.GetLastError() as HttpUnhandledException).GetHtmlErrorMessage();
            info.ErrorSource = (Server.GetLastError() as HttpUnhandledException).GetHtmlErrorMessage();
        }
        info.QueryStringData = "";
        strError += "nnQueryString Data:n-----------------n";
        // Gathering QueryString information
        for (int i = 0; i < Context.Request.QueryString.Count; i++)
        {
            strError += Context.Request.QueryString.Keys[i] + ":tt" + Context.Request.QueryString[i] + "n";
            info.QueryStringData += Context.Request.QueryString.Keys[i] + ":tt" + Context.Request.QueryString[i] + "n";
        }
        strError += "nPost Data:n----------n";
        info.PostData = "";
        // Gathering Post Data information
        for (int i = 0; i < Context.Request.Form.Count; i++)
        {
            strError += Context.Request.Form.Keys[i] + ":tt" + Context.Request.Form[i] + "n";
            info.PostData += Context.Request.Form.Keys[i] + ":tt" + Context.Request.Form[i] + "n";
        }
        strError += "nSession Data:n----------n";
        // Gathering Session information
        for (int i = 0; i < Context.Session.Count; i++)
        {
            strError += Context.Session.Keys[i] + ":tt" + Context.Session[i] + "n";
        }
        strError += "n";
        if (User.Identity.IsAuthenticated)
        {
            strError += "User:tt" + User.Identity.Name + "nn";
            info.UserAccountName = User.Identity.Name;
        }
        info.StackTrace = Server.GetLastError().StackTrace;
        strError += "Exception Stack Trace:n----------------------n" + Server.GetLastError().StackTrace +
            "nnServer Variables:n-----------------n";
        // Gathering Server Variables information
        info.ServerVariables = "";
        for (int i = 0; i < Context.Request.ServerVariables.Count; i++)
        {
            strError += Context.Request.ServerVariables.Keys[i] + ":tt" + Context.Request.ServerVariables[i] + "n";
            info.ServerVariables += Context.Request.ServerVariables.Keys[i] + ":tt" + Context.Request.ServerVariables[i] + "n";
        }
        strError += "n";
    }
    catch (Exception s) { strError += s.Message; }
    info.CompleteSource = strError;
    info.SiteKey = Guid.Parse(System.Configuration.ConfigurationManager.AppSettings["ErrorTrackingKey"]);
    info.IsRead = false;
    info.IsResolved = false;
    info.DateLogged = DateTime.Now;
    info.ErrorCause = ErrorTracking.ErrorCauses.Unknown;
    info.UserAccountID = Guid.Empty;
    info.ErrorSource = "";
    info.UserAccountName = "";
    ErrorTracking.ErrorTrackingServiceClient client = new ErrorTracking.ErrorTrackingServiceClient();
    client.SubmitError(info);
    // Send email to developer
    System.Net.Mail.MailMessage m = new System.Net.Mail.MailMessage();
    m.To.Add(System.Configuration.ConfigurationManager.AppSettings["DebugEmail"]);
    m.Subject = "Error occurred on " + Request.ServerVariables["HTTP_HOST"];
    m.IsBodyHtml = false;
    m.Body = strError;
    System.Net.Mail.SmtpClient c = new System.Net.Mail.SmtpClient();
    try
    {
        c.Send(m);
    }
    catch { }
}

C# Active Directory

2 min read

using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;

.Net has a UserPrincipal built-in class, which will allow you quick access to common objects such as the Name and User Principal name

 // create your domain context
 PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
 // define a "query-by-example" principal - here, we search for a UserPrincipal
 // and with the first name (GivenName) of "Bruce"
 UserPrincipal qbeUser = new UserPrincipal(ctx);
 qbeUser.GivenName = "Steve";
 // create your principal searcher passing in the QBE principal
 PrincipalSearcher srch = new PrincipalSearcher(qbeUser);
 // find all matches
 foreach(var found in srch.FindAll())
 {
   // do whatever here - "found" is of type "Principal" - it could be user, group, computer.....
 }

MVC Remote Validator

< 1 min read Let’s take a look at a brand new MVC 3 validator – RemoteAttribute. The Remote validator is very simple to use and yet extremely powerful. Remote is for situations where it is impossible to duplicate server side validation logic on the client, often because the validation involves connecting to a database or calling a service. If all your other validation uses javascript and responds to the user’s input immediately, then it is not a good user experience to require a post back to validate one particular field. This is where the remote validator fits in.
In this example, we are going to add remote validation to the username field to check that it is unique.

[Remote("ValidateUserName", "Account", ErrorMessage = "Username is not available.")]
public string UserName { get; set; }

Remote has three constructors allowing you to specify either a routeName, a controller and action or a controller, action and area. Here we are passing controller and action and additionally overriding the error message

public ActionResult ValidateUserName(string username)
{
    return Json(!username.Equals("duplicate"), JsonRequestBehavior.AllowGet);
}

Dynamic Linq for searching

< 1 min read

 var predicate = PredicateBuilder.True();
 var q = db.Profiles.Where(t => !t.aspnet_Users.aspnet_Membership.IsLockedOut);
 foreach (string keyword in pars)
 {
     string temp = keyword;
     predicate = predicate.And(t => t.FirstName.StartsWith(temp) || t.LastName.StartsWith(temp));
 }

C# Render Razor View as String

< 1 min read The Razor View Engine is very powerful, easy to use, and just overall great for binding data to HTML. But sometimes you need to render HTML for use in Emails, download pages, generate PDF’s, or other purposes, so it would be neat if you could use the Razor View Engine to generate those for you, and just give you the HTML to do with it as you wish. Luckily we have this somewhat built-in, and here’s a wrapper for it.

public string RenderRazorViewToString(string viewName, object model)
{
  ViewData.Model = model;
  using (var sw = new StringWriter())
  {
    var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
    var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
    viewResult.View.Render(viewContext, sw);
    viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
    return sw.GetStringBuilder().ToString();
  }
}

You can now use it as in the following example

var htmlPage = RenderRazorViewToString("~/Views/Home/myview.cshtml", siteModel);

You can of course extend the method above, and pass it your own ViewData, TempData, RouteData, change the View Engine, enable or disable ClientValidation and UnobtrusiveJavasript, and so on.

C# Add and Edit Office Document Custom Properties

< 1 min read Office documents store a lot more information than is obviously visible at first. Microsoft released a library called DSOfile, which is intended for changing properties of Office files if you don’t have Office installed.
First, you need to download the DSOfile from Microsoft. http://support.microsoft.com/kb/224351

Second, you’ll need to reference it in your project

using DSOFile;

Next, you can start looping through the Office predefined properties of each file. Note, some attributes are read-only.

OleDocumentProperties file = new OleDocumentProperties();
file.Open(@"C:myfile.docx", false, dsoFileOpenOptions.dsoOptionDefault);
int charCount = file.SummaryProperties.CharacterCount;
int wordCount = file.SummaryProperties.WordCount;
int pageCount = file.SummaryProperties.PageCount;
file.SummaryProperties.Author = "John Smith";
file.SummaryProperties.Category = "My Category";
file.SummaryProperties.Company = "My Company Inc.";
file.SummaryProperties.Manager = "David Smith";
file.SummaryProperties.Subject = "Sample files";
file.SummaryProperties.Title = "A very sample file";
file.Save();
file.Close(true);

Those might sometimes not be enough, so surely enough you can add your own custom attributes, and use the NTFS File System as your own personal database.

OleDocumentProperties file = new DSOFile.OleDocumentProperties();
file.Open(@"C:myfile.docx", false, DSOFile.dsoFileOpenOptions.dsoOptionDefault);
string key = "My Custom Key"; /* Use any key you want, these will be saved in the file. */
object value = "My Custom Value";
// Check if file has a certain property set
bool hasProperty = false;
foreach (DSOFile.CustomProperty p in file.CustomProperties)
    if (p.Name == key)
        hasProperty = true;
// If it doesn't have the property, add it, otherwise set it.
// This is the only way I found to loop through the properties
if (!hasProperty)
    file.CustomProperties.Add(key, ref value);
else
    foreach (DSOFile.CustomProperty p in file.CustomProperties)
        if (p.Name == key)
            p.set_Value(value);
// Go through existing custom properties.
foreach (DSOFile.CustomProperty p in file.CustomProperties)
{
    Console.WriteLine("{0}:{1}", p.Name, p.get_Value().ToString());
}
file.Save();
file.Close(true);