Including ASP.NET Membership in an Existing Database

By default, when adding ASP.NET Membership to your web app a new ASP.NET Membership database will be created. However, in many circumstances you may wish the Membership database to be part of your  main application database. To do this simply navigate to \Windows\Microsoft.NET\Framework\v2.0.50727 (use this path even if you are using ASP.NET 4.0 in your application as the Membership database has not changed since ASP.NET 2).

Then find and run the aspnet_regsql.exe program. This will bring up a dialog allowing you to specify the target database to incorporate the ASP.NET Membership tables and stored procedures :

ASP.NET Membership database inclusion dialog

The final step is to ensure that the all connection string references to the membership provider in the web.config point to this database. Don’t forget if you are using Roles that the role provider specified in the web.config must also point to this database (otherwise ASP.NET will automatically create a new database for the roles when the app is run).

ASP.NET MVC Authentication using AccountController

The AccountController class is a controller for user authentication which is included in a default MVC project created with Visual Studio. Prior to using this controller, you will need to modify it so that it no longer refers to the HomeController which you most likely will remove. To do this, replace each of these instances:

return RedirectToAction("Index", "Home");

so they are as below:

return RedirectToAction("Index", "Products");

This will cause the authentication controller to redirect a user to the products controller once an authentication action ends. The default ASP.NET MVC master page has links for a  user to log in/out and register. The MVC Authorize filter facilitates control over which users may access the controller methods. Below is an example of the Authorize filter being  applied to the Delete method in the products controller class:

[Authorize]
public ActionResult Delete(int id) {
NorthwindEntities dbObj = new NorthwindEntities();
var data = dbObj.Products.Where(e => e.ProductID == id).Select(e => e).Single();
return View(data);
}

If a user clicks a delete link to delete a record of a product, the MVC framework is then checked. If the user is currently logged in, the action will proceed.. If the user has not logged in they will then be requested to provide their username and password credentials or else to create a new account. This can be made even more restrictive by specifying user names as part of the filter. Below is an example of the Authorize filter applied so the Delete method is only available to Mike Smith:

[Authorize(Users="Mike Smith")]
public ActionResult Delete(int id) {

Now only Mike Smith can perform the delete actions, all other users will be asked for their credentials. The MVC Authorize filter can even be applied to the whole controller class. Below is an example of the Authorize filter being applied to the ProductsController class, so that only authenticated users can access controller actions:

[HandleError(Order=2)]
[Authorize]
public class ProductsController : Controller {

The Authorize filter has an Order property which works just as the HandleError Order property. If the  Authorize filter is applied for the whole controller level and for a specific action method, the controller-wide setting will always have precedence unless the Order property is used.

Sending Mail from a .NET App Using Amazon SES (Simple Email Service)

Amazon’s Simple Email Service (SES) is a great solution for any project which requires bulk emails. the primary advantage of SES is cost, at $0.10 per 1000 emails sent it is between 5-10x cheaper than other alternatives such as SendGrid. There is a downside to the SES service, however and it is that it currently doesn’t provide an SMTP wrapper so whilst SendGrid and others allow you to simple change your SMTP settings, with SES you will have to do a bit more work.

Amazon (AWS) provides a very useful .NET SDK (complete with dll’s for .NET 2.0, 3.5 and 4.0) which you can simply copy into your project and start calling the Amazon functions from a .NET app such as an ASP.NET site. You can download the SDK here.

The below code shows a simple example of how to use the Amazon AWS SDK in .NET to send emails.

Dim listColl As New System.Collections.Generic.List(Of String)
'//TODO - Write a simple loop to add the recipents email addresses to the listColl object.

Dim client As New Amazon.SimpleEmail.AmazonSimpleEmailServiceClient("aws_public_key_here", "aws_private_key_here")

Dim mailObj As New SendEmailRequest
Dim destinationObj As New Destination(listColl)
mailObj.Source = "from@youremail.com"  '//The from email address
mailObj.ReturnPath = "bounce@youremail.com" '//The email address for bounces
mailObj.Destination = destinationObj

'//Create Message
Dim emailSubjectObj As New Amazon.SimpleEmail.Model.Content("This is the Subject")
Dim emailBodyContentObj As New Amazon.SimpleEmail.Model.Content("This is the Body<br /><em>In Html</em>")

Dim emailBodyObj As New Amazon.SimpleEmail.Model.Body()
emailBodyObj.Html = emailBodyContentObj
Dim emailMessageObj As New Message(emailSubjectObj, emailBodyObj)
mailObj.Message = emailMessageObj

Dim response = client.SendEmail(mailObj)

That’s it, there’s really not a lot of heavy lifting to get starting using SES with .NET. the only thing I didn’t show in the code above is the loop for adding email addresses as strings to the generic collection, this loop will vary a lot depending on your exact requirements.
One thing to note above is that you will need to import the namespace Amazon.SimpleEmail.Model

AWS SES is not as full featured as a lot of solutions such as SendGrid, however it does have several useful features out-of-the-box such as the ability to perform email validation:

Dim testEmail As String = "anemail@domain.com"

Dim verRequest As New VerifyEmailAddressRequest()
verRequest.EmailAddress = testEmail
client.VerifyEmailAddress(verRequest)

This should get you going with SES, I will update this page once the service develops.

ASP.NET MVC Error Handling using the HandleError Filter

ASP.NET Errors can be effectively handled using the HandleError filter, which specifies how exceptions which are thrown in a controller method are to be dealt with (note that ASP.NET MVC supports method filters, which allow for annotating controller methods to change their behavior).
Prior to using the HandleError filter, you will need to enable custom error handling for your ASP.NET MVC app in the web.config file by adding the below line in the system.web section:

<customErrors mode="On" />

The below code snippet show the HandleError filter being applied to the controller class. Thus, any exception which is thrown by an action method in the controller will be handled using the custom error policy.

namespace MVCApplicationDemo.Controllers {
[HandleError]
public class ProductController : Controller {

When the HandleError filter is applied without arguments, any exception thrown by the methods covered by the filter will result in the Views/Shared/Error.aspx view being used which just shows the message “Sorry, an error occurred while processing your request.” To test
this process, attempt to view details of a product which does not yet exist, such as with a URL as below:

http://localhost:51823/Product/Details/999990

The error message can be more specific and you may wish to give the user more detailed info. To do this create a view in the Views/Shared folder named NoRecordErr.aspx with the below content:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>" %>
<asp:Content ID="errTitle" ContentPlaceHolderID="TitleContent" runat="server">
Error Occured
</asp:Content>
<asp:Content ID="errContent" ContentPlaceHolderID="MainContent" runat="server">
<h2>
Sorry, but that record does not yet exist.
</h2>
</asp:Content>

This is a modification of the default error view with a message to show the user that the product request does not yet exist in the database. Next, we can apply the HandleError filter to the Details controller method as in the below snippet:

[HandleError(View="NoRecordErr")]
public ActionResult Details(int id) {

The filter informs the MVC framework that it should use the NoRecordErr view for an exception that is thrown by the Details method. Now, you need to modify the backstop filter to be as show below:

 [HandleError(Order=2)]
public class ProductController : Controller {

An Order value of 2 ensures the controller-wide filter is to be applied only in the event that there is not a HandleError filter with a higher order available. If you do not set a value for Order, the default error view takes precedence.
Now if a user attempts to requests details for a product which does not exist they will be served the new error view. The default error view will be served if other controller methods throw exceptions.

However as it currently stands a user will be informed that they requested a non-existent record for any exception arising from the Details method. Thus you will need to be even more specific.
First, create an exception in the ProductController class which will be used when a record the user has requested is not available:

class NoRecordErr : Exception {
}

The next step is to modify the Details method so that it explicitly checks whether the LINQ query returned a record and if not record was returned throw a new exception.

[HandleError(View="NoRecordErr",
ExceptionType=typeof(NoRecordErr))]
public ActionResult Details(int id) {
NorthwindEntities db = new NorthwindEntities();
var data = db.Products.Where(e => e.ProductID == id).Select(e => e);
if (data.Count() == 0) {
throw new NoRecordErr();
} else {
Product record = data.Single();
return View(record);
}
}

In summery we changed the HandleError filter by including a value for the ExceptionType property, then specifying the type of the exception the filter should to apply to. Now when a NoRecordErr() exception is thrown, the NoRecordErr.aspx view will instead be used. Alternatively, the generic Error.aspx will be used for other exception types (since we applied the controller-wide backstop filter).

Using Sequence in SQL Server 2011 (an Alternative to Identity)

Using the Identity attribute for a column in SQL Server is a very convenient way to auto-increment a field in a row and generate unique ID’s for use as a primary key. SQL Server 2011 introduces Sequence, which is similar in many respects but is offers greater performance and flexibility – read our full tutorial on Using Sequence in SQL Server 2011.

Protect Your ASP.NET App From SQL Parameter Injection

Securing your ASP.NET web app from SQL Injection attacks paramount in the design of any ASP.NET app. Say you are viewing a transaction of customer #448, andyour URL looks something like www.myapplication.com/customer.aspx?customerID=448. What is to stop customer 448 from typing in 449,  and viewing another customer’s transaction details? The situation can even escalate into typing in complete SQL statements and executing them inside the original statements you have coded.  Checking for let’s say a customer sessionID and matching it against the URL and the page will still have to be done by the app developer. This article will demonstrates a simple method of protecting against SQL Injection attacks by checking  for valid parameters in an existing ASP.NET application which can be used in any website. The main idea behind this technique is very simple and includes three components.

The Validation Class
This class contains static methods to check for valid values. For example, if you are expecting a string that is twenty characters long,it can check it for you and notify the application every time itencounters an invalid string on any page. There are several methods implemented in the example code. However, you can add your own and customize them to your needs.

Web.config
This is the file where you keep all of your application keys. So for example, if we would like to check for a customerID and make sure it is an integer, we would add a key named <safeParameters> and set its value to orderID-int32. Now every time our application will encounter an orderID parameter it will automatically check to see if it has a valid integer value.

Global.asax
This file will contain a utility method to match all of our known parameter types to their value. This method will be called isValidParameter. Every time a page is being requested, this method will be executed and will then notify the application if the parameteris valid.

The idea behind these three components working together to prevent SQL Injection attacks  is very simple: prepare all your utility methods to check for valid parameters, define all your valid parameters and check for valid values on each page, take into consideration that if you are using a customerID in twenty pages on your application, they all must be of an integer value. Plugging these components into your application is fairly simple and will ensure that an already   running website will prompt you every time a hacker tries to change a query string regardless of whether your programmers have checked for valid parameters or not. Bear in mind that this is a plug-in, and like all plug-ins it will take its toll on your application performance. A truely secure application will embed any security methods inside the page object only using utility classes to assist. However, if invalid parameters are a problem for you, then this is a good solution.

How to Implement the Example:

Step 1: Add a new utility class and copy and paste the code in parameterCheck.cs into it. Do not forget to change the namespace to fit the needs of the application.

 public class parameterCheck{
public static bool isEmail(string emailString){
return System.Text.RegularExpressions.Regex.IsMatch(emailString,
"['\w_-]+(\.['\w_-]+)*@['\w_-]+(\.['\w_-]+)*\.[a-zA-Z]{2,4}");
}
public static bool isUSZip(string zipString){
return System.Text.RegularExpressions.Regex.IsMatch(zipString ,"^(\d{5}-\d{4})|(\d{5})$");
}
}

Step 2: In the Web.config file, add a key under the <appSettings> tag. This key will contain all of the parameters you wish to check for and the types they need to be. The name of the key is <safeParameters>, and the value can be for example: ordered-int32,customerEmail-email.

<appSettings>
<add key="safeParameters" value="OrderID-int32,CustomerEmail-email,ShippingZipcode-USzip" />
</appSettings>

Step 3: In your Global.asax copy and paste the code in the example into your Application_BeginRequest method.

Continues…

ASP.NET Session State Best Practices

Session state is an integral part of many ASP.NET apps but it can also be a drag on performance or result in application errors if used inappropriately. Here are our ASP.NET Session State best practices to ensure you won’t be tripped up by any gotchas:

  • Do not overuse Session State for user data storage.
    One of the problems with Session State is that it is so convenient for user data storage – just store anything using Session["someName"] = someName.Text . This leads developers to overuse Session State and store data that would be better handled by another technique (for example, you can use ASP.NET Membership Profiles to store and retrieve user settings, or use caching for storing miscellaneous items).
  • Try to avoid storing complex objects in Session State.
    Session Sate can store objects of any type (including objects you create) however, they are stored by serializing and then de-serializing them which results in a big performance penalty. If possible try to only store ‘basic’ types such as Integer, Decimial, String, DateTime, GUID etc
  • Use an Out of Process mode if possible
    Session State provides for three configuration modes – In Process, Out of Process using stateview and Out of Process using SQL Server.
    In Process stores the session state data in memory with the same process as the application, this has the advantage of being the fastest mode but it also means that all session data is lost when the app restarts. The app restart is more common than many developers believe, in addition to server and IIS restarts any change in the web.config or global.asax file will restart the app and all session state data can be lost.
    Out of Process (stateserver) stores the session data in memory but in a different process, if you are running a web farm this can even be on a separate machine. Out of Process (SQLServer) stores the session data in SQL Server which is the most stable as it will be recoverable in all scenarios except a database failure but it is also the slowest. Both Out of Process modes protect the session data from loss due to an app restart.
  • Do not store sensitive data in Session State.
    SessionID’s which identify user sessions are sent in clear text and can be intercepted by nefarious users. Once a user’s SessionID has been obtained, data stored in the Session State associated with that SessionID can be easily accessed. Thus you should avoid using Session State to store sensitive data or use SSL or encryption of the data to protect it.
  • Allow users to log out of an application
    You should allow users to log out of the app, upon logon the app should call the Abandon method. This will reduce the scope for a malicious user to get hold of  the unique identifier in the URL and then use it for retrieving user data stored in session state.

ASP.NET Security Tutorial

Securing an ASP.NET application is paramount for any project. Here (in no particular order), in this tutorial we present the primary ASP.NET security best practices:

  • Ensure system patches are fully up-to-date
    Not really an ASP.NET specific best practice but since ASP.NET relies on the underling OS for its operation it is essential to ensure the OS to fully patched with the latest security updates.
  • Secure all connection strings
    Typically an app’s database will stored its most sensitive data so preventing unauthorized reading of the connection string is a must. The connection string should be stored in the web.config file and not in the code behind for pages and also not in the SqlDataSource control or other data source controls. For maximum security encrypt sensitive settings in config files – see Encrypt Connection Strings in ASP.NET for details.
  • Use parameterized queries or stored procedures instead of creating SQL commands by concatenating strings.
    It is possible to generate   the SQL for a command by building strings like below:

    SQLCmdStr = "Select * from users where username =' " & usernameTxt.Text  & "'

    This however allows for the possibility of SQL injection attacks by users directly typing SQL commands into text boxes which are then executed. Instead you can use a parameterized query as below:

    SQLCmdStr = “Select * from Users where Lastname =@LastName”
    SQLCmd.Parameters.Add(New SQLParameter(“@LastName”, ddl.SelectedItem.text))
  • Encrypt any sensitive data stored in View State
    View State is sometimes used to stored sensitive data sure as user names or even account numbers. Since View State is posted back to the server on every postback this data could be intercepted and read, therefore when any sensitive data is stored in View State the the page’s ViewStateEncryptionMode property should be set to true.
  • User input validation
    Always validate user input on the server even if it has been validated on the client since a user can easily bypass most client side validation by turning off javascript. The below code shows how to use Regex on the server-side to valid input:
  • using System.Text.RegularExpressions ;
    
    // Instance method:
    Regex regObj = new Regex(@"^[a-zA-Z'.\s]{1,40}$");
    Response.Write(regObj.IsMatch(Request.QueryString["InputName"]));
    
    // Static method:
    if (!Regex.IsMatch(Request.QueryString["InputName"],@"^[a-zA-Z'.\s]{1,40}$"))
    {
       // Name does not match expression
    }

    Note that user input does not only come from values input by the user on a form on the page. ASP.NET apps also take data form QueryStrings and cookies, these must also be validated in the same manner as input data.

    Continues…