Best asp.net questions in May 2012

How is everyone storing connectionstrings?

9 votes

I was wondering if people could post their solution to the ongoing problem of local databases and different connectionstrings among many developers in one project within source control?

More specifically, I'm talking about the problem where a project that is in source control and has many developers with a local database each. Each developer has their own connection string (named instance, default instance, machine name, username, password, etc). Every check in overrides the previous version and pulling the latest version results in using someone else's connection string.

So, people, which solution are you using for this problem? Extra points for explanations on why their solution works, pros, and cons.

EDIT Keep in mind that this answer shouldn't be targeted only to an enterprise environment where you have full control of the setup. The right solution should work for everyone: enterprise, startup, and open source devs.

Thanks!

To me, your question seems to imply one of two outcomes:

  1. A connection string is specified in the Web.config file that is generic enough to work for all local versions of the database. You've indicated that this isn't an ideal setup in environments where you don't have complete control.
  2. Each developer is required to supply his or her own connection string that is never checked into source control.

A few others have already covered the first scenario. Use localhost and follow a convention for the database name. For option 2, I'd recommend specifying a config source that doesn't get checked into source control:

<configuration>
  <connectionStrings configSource="connectionStrings.config"/>
</configuration>

EDIT:

connectionStrings.config

<connectionStrings>
  <add name="Name" 
    providerName="System.Data.ProviderName" 
    connectionString="Valid Connection String;" />
</connectionStrings>

From: http://msdn.microsoft.com/en-us/library/ms254494(v=vs.80).aspx

connectionStrings.config would be a file in the root of the project that you specifically excluded from source control. Each developer would be required to provide this file when working locally. Your production connection string could be substituted via a Web.config transformation on build / deployment.

Validating for large files upon Upload

7 votes

I am working with c# MVC 2 and ASP.NET. One of my forms includes a file input field which allows a use to select any file type which will then be converted into a blob and saved into the database. My problem is that whenever a user selects a file that exceeds a certain amoutn of Mb (about 8) I get a page error that says the following:

The connection was reset
The connection to the server was reset while the page was loading.

I don't mind that there's an 8Mb limit to the files the users are uploading however I need to stop the current error from happening and display a proper validation message (preferably with the ModelState.AddModelError function). Can anybody help me? I can't seem to 'catch' the error before anything else happens in the page since it's happening before it arrives in the upload function within the controller.

One possibility is to write a custom validation attribute:

public class MaxFileSizeAttribute : ValidationAttribute
{
    private readonly int _maxFileSize;
    public MaxFileSizeAttribute(int maxFileSize)
    {
        _maxFileSize = maxFileSize;
    }

    public override bool IsValid(object value)
    {
        var file = value as HttpPostedFileBase;
        if (file == null)
        {
            return false;
        }
        return file.ContentLength <= _maxFileSize;
    }

    public override string FormatErrorMessage(string name)
    {
        return base.FormatErrorMessage(_maxFileSize.ToString());
    }
}

and then you could have a view model:

public class MyViewModel
{
    [Required]
    [MaxFileSize(8 * 1024 * 1024, ErrorMessage = "Maximum allowed file size is {0} bytes")]
    public HttpPostedFileBase File { get; set; }
}

controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        if (!ModelState.IsValid)
        {
            // validation failed => redisplay the view
            return View(model);
        }

        // the model is valid => we could process the file here
        var fileName = Path.GetFileName(model.File.FileName);
        var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
        model.File.SaveAs(path);

        return RedirectToAction("Success");
    }
}

and a view:

@model MyViewModel

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(x => x.File, new { type = "file" })
    @Html.ValidationMessageFor(x => x.File)
    <button type="submit">OK</button>
}

Now of course for this to work you will have to increase the maximum allowed upload file size in web.config to a sufficiently large value:

<!-- 1GB (the value is in KB) -->
<httpRuntime maxRequestLength="1048576" />

and for IIS7:

<system.webServer>
    <security>
        <requestFiltering>
           <!-- 1GB (the value is in Bytes) -->
            <requestLimits maxAllowedContentLength="1073741824" />
        </requestFiltering>
    </security>
</system.webServer>

We could now bring our custom validation attribute a step further and enable client side validation to avoid wasting bandwidth. Of course verifying the file size before uploading is only possible with HTML5 File API. As a consequence only browsers that support this API will be able to take advantage of it.

So the first step is to make our custom validation attribute implement the IClientValidatable interface which will allow us to attach a custom adapter in javascript:

public class MaxFileSizeAttribute : ValidationAttribute, IClientValidatable
{
    private readonly int _maxFileSize;
    public MaxFileSizeAttribute(int maxFileSize)
    {
        _maxFileSize = maxFileSize;
    }

    public override bool IsValid(object value)
    {
        var file = value as HttpPostedFileBase;
        if (file == null)
        {
            return false;
        }
        return file.ContentLength <= _maxFileSize;
    }

    public override string FormatErrorMessage(string name)
    {
        return base.FormatErrorMessage(_maxFileSize.ToString());
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = FormatErrorMessage(_maxFileSize.ToString()),
            ValidationType = "filesize"
        };
        rule.ValidationParameters["maxsize"] = _maxFileSize;
        yield return rule;
    }
}

and all that's left is configure the custom adapter:

jQuery.validator.unobtrusive.adapters.add(
    'filesize', [ 'maxsize' ], function (options) {
        options.rules['filesize'] = options.params;
        if (options.message) {
            options.messages['filesize'] = options.message;
        }
    }
);

jQuery.validator.addMethod('filesize', function (value, element, params) {
    if (element.files.length < 1) {
        // No files selected
        return true;
    }

    if (!element.files || !element.files[0].size) {
        // This browser doesn't support the HTML5 API
        return true;
    }

    return element.files[0].size < params.maxsize;
}, '');

MembershipUser.IsOnline is true even after logout

7 votes

I'm currently creating a website using Visual Studio 2010. I'm using the default membership schema in SQL Server 2008 for user authentication. Now I'm facing the following problem.

When a user logs out, the membership.IsOnline property of that user should be set to false. However that it is not happening; membership.IsOnline property of that user is still true.

I'm using the LoginStatus control to provide a logout link to the user.

I have tried to follow User.IsOnline = true even after FormsAuthentication.SignOut(). But results nothing.

AFAIK, FormsAuthentication.SignOut doesn't have a direct relationship to Membership system. Thus, you have to update the LastActivityDate manually as you mentioned in your question. And use Membership.UserIsOnlineTimeWindow instead of -2.

From MSDN

The UserIsOnlineTimeWindow property value is checked during the call to GetNumberOfUsersOnline. If the LastActivityDate for a user is greater than the current date and time minus the UserIsOnlineTimeWindow value in minutes, then the user is considered online. You can determine whether a membership user is considered online with the IsOnline property of the MembershipUser class.

MembershipUser user = Membership.GetUser(false);

FormsAuthentication.SignOut();

user.LastActivityDate = DateTime.Now.AddMinutes(-(Membership.UserIsOnlineTimeWindow + 1));
Membership.UpdateUser(user);

some questions around the use of ConcurrentDictionary

7 votes

I am currently writing a C# application. I am new to using a ConcurrentDictionary so have some questions around its thread safety. Firstly, this is my dictionary:

    /// <summary>
    /// A dictionary of all the tasks scheduled
    /// </summary>
    private ConcurrentDictionary<string, ITask> tasks;

I instantiate this in my class and use it to track all of my objects that implement ITask. I want ensure my setup will work correctly in a multi threaded environment.

If multiple threads want to get the count of the number of items in the ConcurrentDictionary, do I need to lock it?

If I want to get a particular key from the dictionary, get the object of that key and call a method on it, do I need to lock it? eg:

    /// <summary>
    /// Runs a specific task.
    /// </summary>
    /// <param name="name">Task name.</param>
    public void Run(string name)
    {
        lock (this.syncObject)
        {
            var task = this.tasks[name] as ITask;
            if (task != null)
            {
                task.Execute();
            }
        }
    }

Keeping mind multiple threads could call the Run method looking to call the Execute method of ITask. My aim is to have everything thread safe and as performant as possible.

The methods and properties of the ConcurrentDictionary themself are completely thread safe:

http://msdn.microsoft.com/en-us/library/dd287191.aspx

Represents a thread-safe collection of key-value pairs that can be accessed by multiple threads concurrently.

This includes the Count property:

Count has snapshot semantics and represents the number of items in the ConcurrentDictionary at the moment when Count was accessed.

However this does not mean that the objects held inside the dictionary are themselves thread safe. That is, there is nothing stopping two threads from accessing the same Task object and trying to run the Execute method on it. If you'd like serialised (locked) access to each individual task for the Execute method, then I suggest having a locking object inside Task and locking when running Execute:

public class Task
{
    private object _locker = new object();

    public void Execute()
    {
        lock (_locker) {
           // code here
        }
    }
}

This ensures that at least every individual task doesn't have multiple threads running Execute. I'm guessing this is what you're after from the context of the question and the names of the classes and methods.

Is there a need to secure connection string in web.config?

6 votes

So I am using connection strings in my web.config using SQL authentication.

Of course people say this could be a vulnerability as you are storing password in plaintext.

However, from what I know, IIS never serves web.config, and web.config should only have read access to administrators and IIS anyway. So if the hacker has gained access to the webserver, then it won't matter what encryption I use because the private key will be on the webserver.

Wouldn't encrypting connection string be classified as security through obfuscation?

Is it worth encrypting web.config connection string and storing the private key on the webserver?

Further, of course if I don't use SSL, I am transmitting connection string over HTTP in plaintext. If I use SSL then this problem should be mitigated as well.

I wouldn't say that storing a plaintext password in Web.config is a security vulnerability, in and of itself. But encrypting the password is a useful defense-in-depth measure, not just security through obscurity:

  1. What if IIS is misconfigured to serve Web.config?
  2. What if a security vulnerability is discovered in ASP.NET (like the padding oracle vulnerability) that allows anyone to download Web.config?
  3. There are varying degrees of access to the Web server, from full administrative privileges to server-side code injection. If an attacker can only manage to do the latter, he might be able to read Web.config but might not be able to access the machine keys, especially if your application is running under partial trust.

In the end, it's up to you to decide if the risk of storing plaintext passwords in Web.config is acceptable. Of course, if Windows authentication is an option, then you may want to consider using that instead of SQL authentication.

UPDATE: When talking about security, it's a good idea to identify the assets and the threats. In this case, the asset is sensitive data in the database (if the data is unimportant, then why bother protecting it with a password?), and the threat is the possibility of an attacker somehow gaining access to Web.config and thus the database as well. A possible mitigation is to encrypt the database password in Web.config.

How much of a risk is it? Do we really have to plan for such an astronomically rare occurrence?

This mitigation has already proved its worth once: when the ASP.NET padding oracle vulnerability was discovered. Anyone who stored a plaintext password in Web.config was at risk; anyone who encrypted the password wasn't. How certain are you that another similar vulnerability in ASP.NET won't be discovered in the next few years?

Should we also encrypt source code and decrypt on run-time? Seems excessive to me.

So what if an attacker does get access to your source code? What's the asset you're protecting, and what's the threat you're concerned about? I think that in many cases, source code is much less valuable than data. (I'm thinking here about off-the-shelf commercial and open-source software which anyone can obtain.) And if your source code is valuable, maybe obfuscation is something to think about.

I feel if they already have even limited access to your box, then your host has failed or you've installed vulnerable services already.

What about security vulnerabilities in ASP.NET or your code? They do pop up from time to time.

My concern is standard practices. Is it a standard?

Microsoft has recommended encrypting connection strings.

What you should do is evaluate the risk that storing a plaintext password poses:

  • How likely is it that an attacker will be able to discover and exploit a security vulnerability that exposes Web.config? Based on past history, I'd say the likelihood is low (but not "astronomically" low).
  • How valuable or sensitive is your data? If all you're storing is pictures of your cat, then maybe it doesn't matter much whether an attacker gets your database password. But if you're storing personally identifiable information, then from a legal standpoint, I'd say you should take all possible measures to secure your application, including encrypting your connection strings.

need some idea about how to manage roles in my application (ASP.NET MVC3)

6 votes

I'm developing some website which is a kind of online workplace, there will be some users and some ongoing computer programming projects, and each user can have multiple roles, for example one particular user can be a project manager for an project and a developer for another project. naturally the project manager has more authority than the developer in the project. my question is how to manage this in my code neatly? I was going to use my custom Role Provider and use the Authorize attribute with this, but it's not sufficient , since I'd need the project Id plus the user Id to find the role of user in an specific project.

First all you will have to create additional tables for your extended role management like projects and there relationship with the users in context of operations, which might be your controller's actions.

One way of doing is to create your own table for roles. In that case you will only use only Asp net membership users, but it all depends your requirements.

Secondly you have to handle it in MVC, In my opinion the best way is to implement it through your own custom Authorization attribute, and decorate your controller's actions with your custom authorization attribute instead of [Authorization] attribute.

Its very simple.

[CustomAuthorize]
//[Authorize]
public ActionResult GetProjectTasks(string projectname)
{

}

For that you have to inherent your class from FilterAttribute and also have to implement IAuthorizationFilter interface.

 public void OnAuthorization(AuthorizationContext filterContext)
    {
        HttpCookie authCookie = filterContext.HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName];

        if (authCookie != null)
        {
            FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            var identity = new GenericIdentity(authTicket.Name, "Forms");
            var principal = new GenericPrincipal(identity, new string[] { authTicket.UserData });
            filterContext.HttpContext.User = principal;
        }

        var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
        var action = filterContext.ActionDescriptor.ActionName;
        var user = filterContext.HttpContext.User;
        var ip = filterContext.HttpContext.Request.UserHostAddress;

        var isAccessAllowed = CustomAuthenticationLogic.IsAccessAllowed(controller, action, user, ip);
        if (!isAccessAllowed)
        {
            // Code if user is authenticated
            FormsAuthentication.RedirectToLoginPage();
        }            
    }

In the method OnAuthorization, you can get all the information which you might be require in your custom authorization logic like HttpContext, Controller name, Action name. You have to just call your custom authentication logic from this method. Your custom authentication logic might look like the following.

 public class CustomAuthenticationLogic
{
    public static bool IsAccessAllowed(string controller, string action, IPrincipal user, string ip)
    {
        //
        // Your custom logic here              
        //              
    }
} 

I can send the images and rar files but that files was corrupted using asp.net?

6 votes

i am using asp.net and c#.net to send the mail with large attachments(max 10mb), that the reason i can convert the files, .txt,.doc,.xls file are perfectly sending but images and rar file corrupted what is the problem please give me any suggestion , My code is

 DataSet ds = SqlHelper.ExecuteDataset(con, "usp_GetEmailSettings", Session["UserID"].ToString());
                message.To.Add(ds.Tables[0].Rows[0]["Email"].ToString());
                message.CC.Add(ds.Tables[1].Rows[0]["EmailID"].ToString());
                message.Subject = ds.Tables[0].Rows[0]["Email_Subject"].ToString();
                message.From = new System.Net.Mail.MailAddress(ds.Tables[1].Rows[0]["EmailID"].ToString());
                message.Body = ds.Tables[0].Rows[0]["Email_Body"].ToString() +
                                       "<br/><br/> <font size='2.0em'>Submission Number : " +filename+"<br/> DBA Name : " +txtDBAName.Text + "<br/> Insured Name : " +TxtInsured.Text + "<br/> Additional Comments : " + txtcomment.Value ;
                message.IsBodyHtml = true;
                string attachId;
                System.Net.Mail.Attachment at;
 // Get the HttpFileCollection and Attach the Multiple files
                HttpFileCollection hfc = Request.Files;
                if (hfc.Count > 0)
                {
                    for (int i = 0; i < hfc.Count; i++)
                    {
                        HttpPostedFile hpf = hfc[i];
                        if (hpf.ContentLength > 0)
                        {
                            if (i == 0)
                            {
                                string[] ext = System.IO.Path.GetFileName(hpf.FileName).Split('.');
                                attachId = filename + "." + ext[1];
                                at = new System.Net.Mail.Attachment(fluuploader.FileContent, attachId);
                            }

                            else
                            {
                                string[] ext = System.IO.Path.GetFileName(hpf.FileName).Split('.');
                                attachId = filename + "(" + i + ")" + "." + ext[1];
                                at = new System.Net.Mail.Attachment(fluuploader.FileContent, attachId);
                            }
                            at.TransferEncoding = System.Net.Mime.TransferEncoding.SevenBit;
                           // at.TransferEncoding = System.Net.Mime.TransferEncoding.QuotedPrintable;                       
                            message.Attachments.Add(at);
                        }

                    }
                }
 smtp.Timeout = 9999999;
                smtp.Send(message);  

web.config my code is

<httpRuntime executionTimeout="240" maxRequestLength="20480"/>

at.TransferEncoding = System.Net.Mime.TransferEncoding.SevenBit; i can give the comment in that line doesnot send the large files but all are perfectly working but i have send the large files maximum 10mb , pls give me suggestion

Unless there is some black magic taking place behind the scenes, I think you need to swap out fluuploader.FileContent with hpf.InputStream. Also, I find it helps to set the Position of the InputStream to 0. Your final code inside the for loop should look something like this:

    HttpPostedFile hpf = hfc[i];

    if (hpf.ContentLength > 0)
    {
        hpf.InputStream.Position = 0;

        if (i == 0)
        {
            string[] ext = System.IO.Path.GetFileName(hpf.FileName).Split('.');
            attachId = filename + "." + ext[1];
            at = new System.Net.Mail.Attachment(hpf.InputStream, attachId);
        }

        else
        {
            string[] ext = System.IO.Path.GetFileName(hpf.FileName).Split('.');
            attachId = filename + "(" + i + ")" + "." + ext[1];
            at = new System.Net.Mail.Attachment(hpf.InputStream, attachId);
        }

        message.Attachments.Add(at);
    }

How to set IHttpAsyncHandler a timeout?

6 votes

I've tried to set the executionTimeout in the web.config file:

<compilation debug="false" targetFramework="4.5">
<httpRuntime executionTimeout="30"/>

Looking at the IIS Manager Requests page I can see the requests are not being terminated after 30 seconds.
Should I implement a Timer inside my IHttpAsyncHandler?

With the apparent lack of built-in support for IHttpAsyncHandler timeouts, presumably you must manage your own timeout. Perhaps this is by design; after all you are choosing an asynchronous pattern - who does MSFT think they are trying to set a default timeout for your long running task?

What I would do is use ThreadPool.RegisterWaitForSingleObject to manage your pooling with an appropriate timeout. Here is a code sample I use to avoid waiting on a web service that never returns:

private const int REQUEST_TIMEOUT = 30000;   // miliseconds (30 sec)
private void CallService()
        {
        try {
             string url = "somewebservice.com";
             WebRequest request = WebRequest.Create(url);

             // Asynchronously fire off the request
             IAsyncResult result = request.BeginGetResponse(new AsyncCallback(MyRoutineThatUsesTheResults), request);

             // Handle timed-out requests
             ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(RequestTimeout), request, REQUEST_TIMEOUT, true);
         }
         catch (Exception ex) {
              _logger.Error("Error during web service request.", ex);
         }

private void RequestTimeout(object state, bool timedOut)
        {
            if (timedOut) {
                WebRequest request = (WebRequest)state;
                _logger.WarnFormat("Request to {0} timed out (> {1} sec)", request.RequestUri.ToString(), REQUEST_TIMEOUT / 1000);
                request.Abort();
            }
        }

You will need an IAsyncResult to work with this approach but that's an established pattern you shouldn't have trouble running down samples about.

Also, you will run into issues when IIS decides to recycle your app pool / tear down your app domain while your polling is still running. If that's a condition you want to handle, you can use HostingEnvironment.RegisterObject.

How can I prevent the dropdown from opening in a DropDownList?

6 votes

I have a custom table which I'd like to use as the DropDown portion as a DropDownList.

Table

Ideally, when users click on a DropDownList, it should show the custom table instead of the usual drop down. I thought it'd be easy to prevent the dropdown from opening without disabling the DropDownList control, however that doesn't appear to be the case.

Is there an easy way to prevent a DropDownList from opening without disabling it?

It's possible to stop the dropdownlist from showing by using jQuery's event.preventDefault in the mousedown event (demo: http://jsfiddle.net/RCCKj).

Also see this related question: stop chrome to show dropdown list when click a select

AJAX IRCX Client and Server

5 votes

I am currently developing an IRCX AJAX Chat based system and have a few questions regarding the Server and Client implementation; Any suggestions are welcome:

Server

Should this be implemented as a Web Service, or a Windows Form application? I have experience in developing Windows Forms based servers, however I am wondering if this would be better implemented as a Web Service and if so, why?

Client

How are Web Based Clients implemented today and what is the preferred method to implement a Web Based Client?

My solution so far are

  • ASP.NET Web Forms with an AJAX Update Panel (This seems the most viable)
  • Using jQuery connecting to the web service with a JavaScript timeout

Polling

How frequently should the server be polled for new messages? 0.5 seconds seems a bit excessive and anything between 2 or 3 seconds seems sluggish.

Thanks for your input.

I believe using ASP.NET (Sockets and an Update Panel) seems to be the best approach. Using jQuery in this context now seems a bit invalid because it would not maintain a persistent state with the Chat Server which is required for Real Time Communication.

An alternative way I found would be using a Web Sockets and Backbone.JS to deal with the data returned from the server.

http://blog.fogcreek.com/the-trello-tech-stack/

Is it faster to query a List<T> or database?

5 votes

I have recently had several situations where I need different data from the same table. One example is where I would loop through each "delivery driver" and generate a printable PDF file for each customer they are to deliver to.

In this situation, I pulled all customers and stored them into

List<Customer> AllCustomersList = customers.GetAllCustomers();

As I looped through the delivery drivers, I'd do something like this:

List<Customer> DeliveryCustomers = AllCustomersList.Where(a => a.DeliveryDriverID == DriverID);

My question: Is the way I'm doing it by querying the List object faster than querying the database each time for customer records associated with the delivery driver?

There isn't an accurate number for amount of rows that if you pass it you should query the DB instead in in-memory List<T>

But the rule of thumb is, DB are designed to work with large amount of data and they have optimization "mechanisms" while in in-memory there aren't such things.

So you will need to benchmark it to see if the round-trip to DB is worth it for that amount of rows for each time it's important to you

"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil"

5 votes

I have been reading a lot of articles explaining how to set up Entity Framework's DbContext so that only one is created and used per HTTP web request using various DI frameworks.

My question is...why is this a good idea in the first place? What advantages do you gain by using this approach? Are there certain situations where this would be a good idea? Are there things that you can do using this technique that you can't do when instantiating DbContexts per repository method call?

Please forgive my ignorance, but I'm really trying to understand why.

Let start by repeating Ian: Having a single DbContext is a bad idea, since it is not thread-safe, but I expect you already know that and just want to know what not just inject a new instance (thus with a transient lifestyle) of the DbContext into anyone who needs it.

Let me start by saying that registering a DbContext as transient could work, but typically you want to have a single instance of such a unit of work within a certain scope. In a web application, it is practical to define such a scope on the boundaries of a web request; thus a Per Web Request lifestyle. This allows you to let a whole set of classes operate within the same context. In other words, they operate within the same business transaction.

When you have no intention of letting a whole set of operations operate inside the same context, in that case the transient lifestyle is fine, but there are a few things to watch:

  • Since every type gets its own instance, every class that changes the state of the system, needs to call context.SaveChanges() (otherwise changes would get lost). This can complicate your code, and adds a second responsibility to the code (the responsibility of controlling the context), and is a violation of the Single Responsibility Principle.
  • You need to make sure that entities (loaded and saved by a DbContext) never leave the scope of such a class, because they can't be used in the context of another class. This can complicate your code enourmously, because when you need those entities, you need to load them again by id, which could also cause performance problems.
  • Since DbContext implements IDisposable, you probably still want to dispose all created instances. If you want to do this, you basically have two options. You need to dispose them in the same method right after calling context.SaveChanges(), but in that case the the business logic takes ownership of an object it gets passed on from the outside. The second option is to dispose all created instances on the boundary of the http context, but in that case you still need some sort of scoping to let the container know when those instances need to be disposed.

Another option is to not inject a DbContext at all. Instead, you inject a DbContextFactory that is able to create a new instance (I used to use this approach in the past). This way the business logic controls the context explicitly. If might look like this:

public void SomeOperation()
{
    using (var context = this.contextFactory.CreateNew())
    {
        var entities = this.otherDependency.Operate(
            context, "some value");

        context.Entities.InsertOnSubmit(entities);

        context.SaveChanges();
    }
}

The plus side of this is that you control the DbContext explicitly and it is easy to set this up. It also allows you to use a single context in a certain scope, which has clear advantages, such as running code in a single business transaction, and being able to pass around entities, since they originate from the same DbContext. The downside is that you will have to pass around the DbContext from method to method (which is called method injection). Note that in a sense this solution is the same as the 'scoped' approach, but now the scope is controlled in the application code itself (and is possibly repeated many times). It is the application who is responsible for creating and disposing that unit of work. Since the DbContext is created after the dependency graph is constructed, constructor injection is out of the picture and you need to revert to method injection.

Method injection isn't that bad, but when the business logic gets more complex, and more classes get involved, you will have to pass it from method to method, from class to class, which just complicates the code a lot (I've seen this in the past). For a simple application, this approach will do just fine though.

Because of the downsides this factory approach has for bigger systems, another approach can be useful and that is the one where you let the container or the infrastructure code / Composition Root manage that unit of work. This is the style that your question is about.

By letting the container or the infrastructure handle this, your application code keeps clean from having to create, (optionally) commit and dispose that instance, which keeps the business logic simple and clean (just a single responsibility). There are some difficulties with this approach. For instance, were do you commit and dispose that instance?

Disposing a unit of work can be done at the end of the web request. Many people however, incorrectly assume that this is also the place to commit the unit of work. However, at that point in the application, you simply can't determine for sure that the unit of work may actually be committed. When the application code threw an exception, you simply don't want to commit.

The real solution is again to explicitly program some sort of scope, but this time do it inside the composition root. When abstracting all business logic behind the command / handler pattern, you will be able to write a decorator that can be wrapped around each command handler that allows to do this. Example:

class TransactionalCommandHandlerDecorator<TCommand>
    : ICommandHandler<TCommand>
{
    private readonly DbContext context;
    private readonly ICommandHandler<TCommand> decorated;

    public TransactionCommandHandlerDecorator(
        DbContext context,
        ICommandHandler<TCommand> decorated)
    {
        this.context = context;
        this.decorated = decorated;
    }

    public void Handle(TCommand command)
    {
        this.decorated.Handle(command);

        context.SaveChanges();
    } 
}

This ensures that you only need to write this infrastructure code once. Any solid DI container allows you to configure such a decorator to be wrapped around all ICommandHandler<T> implementations.

How do I force compilation of ASP.NET MVC views?

5 votes

I have a Windows Azure web role that contains a web site using ASP.NET MVC. When an HTTP request arrives and a page is first loaded the view (.aspx or .cshtml) is compiled and that takes some time and so the first time a page is served it takes notable longer than later serving the same page.

I've enabled <MvcBuildViews> (described in this answer) to enforce compile-time validation of views, but that doesn't seem to have any effect on their compilation when the site is deployed and running.

Azure web roles have so-called startup tasks and also a special OnStart() method where I can place whatever warmup code, so once I know what to do adding that into the role is not a problem.

Is there a way to force compilation of all views?

Turns out there's ASP.NET Precompilation that can be performed using ClientBuildManager.PrecompileApplication and mimics the on-demand compilation behavior, but just compiles every page. Tried it - the first load looks notably faster.

PHP vs ASP.NET static variables

5 votes

Static variables in ASP.NET caught me off guard today. Then i became freaked out, because this means either i have a fundamental misunderstanding of static variables in the world of the web or ASP.NET does not act like i thought it would.

So in ASP.NET

public class MyClass {
    public static bool myVar = true;    
}

If ASPUserA sets MyClass.myVar = false every other user on the system would experience these changes. So, ASPUserB would have myVar = false. My Source: http://www.foliotek.com/devblog/avoid-static-variables-in-asp-net/

class MyClassPHP {
    public static $myVar = false;
}

If PHPUserA sets MyClass::$myVar = true does this mean that every user on the system experiences these changes???

Thank you.


Upon further research i did this;

class MyClassPHP {
    public static $myVar = 0;
}

Then i had users who went to a page do this

MyClassPHP::$myVar++;
echo MyClassPHP::$myVar;

It always was 1. No matter how many times i refreshed or simultaneous connections... WOHHH that was a great conclusion, or else i am screwed!!


ASP.NET update

Upon further research and testing things i found this.

public partial class MyPage : System.Web.UI.Page
{
    public static int myInt = 0;

    protected void Page_PreInit(object sender, EventArgs e)
        myInt++;
    }

}

Then my page can display myInt.

Between the browsers (Firefox and chrome) the myInt was progressively higher as i refreshed the page. So this does not matter if your class is static. It only matters if you have static variables. They are application wide.

When running in IIS:

A static variable is not "page" specific. It is "AppDomain" specific. The only relation to the "page" would be the path (so to speak) of the variable (MyProject.MyPage.MyVariable for example). Because all users of your application are running in the same AppDomain (i.e. same IIS application folder), then they will all use the same static variable. So... eventually your users are going to see each each other's information since they are all sharing that one single static variable.

PHP however tracks statics PER USER INSTANCE, so I guess you could call them "safer from the singleton dangerzone".

ASP.NET MVC4 routing issue

5 votes

I've searched Stack for ages, read the MSDN docs and used Bing but cannot see why this won't work! I've got the relevant code below + the routes. The route called Browse works just fine, but the productCode param for the Details route is always equal to nothing. If I make any mods I keep getting the 'resource not found' 404 page.

' Lives in controller called 'Details'
' Usage: site.com/details/abc123
Function Index(productCode As String) As ActionResult

' Lives in controller called 'Browse'    
' Usage: site.com/browse/scifi/2
Function Index(genre As String, Optional page As Integer = 1) As ActionResult

The routes are:

routes.MapRoute( _
        "Browse", _
        "{controller}/{genre}/{page}", _
        New With {.controller = "Browse", .action = "Index", .id = UrlParameter.Optional, .page = UrlParameter.Optional}
    )

    routes.MapRoute( _
        "Details", _
        "details/{productCode}", _
        New With {.controller = "Details", .action = "Info", .productCode = UrlParameter.Optional}
    )

The order does matter when defining your routes.

When you request site.com/details/abc123 I think it matches your first route.

You will get

controller = "details"

action = "Index"

genre = "abc123"

Which is why your productCode is null.

Switch the two route.MapRoute statements around, it should fix your problem.

Your second route does have action set to info rather than index, but i'm assuming that is a typo?

How can I calculate the numbers of month between two dates in C#

5 votes

Now I am working with asp.net and C#
I would like to know how to calculate the numbers of Month between two dates.Is there any method to calculate it in C#.

Eg1. Date1 = "2011/11/01"
Date2 = "2012/02/01"
Result. Numbers of Month =3

 Eg2.  Date1 = "2012/01/31"
       Date2 = "2012/02/01"  
Result. Numbers of Month =1

 Eg3.  Date1 = "2012/01/01"  
       Date2 = "2012/02/28"
 Result. Numbers of Month =1

The result will strange .It doesn't take the days of the month into account. But I would like to get this result because of system requirement.

With regards.

This will give difference between months:

int months = (Date2.Year - Date1.Year) * 12 + Date2.Month - Date1.Month;