Best asp.net-mvc questions in March 2012

Using Mini-Profilier with EF 4.3 & MVC 4 without creating the database

13 votes

I have an issue where we are using EF 4.3 Code First against an existing database. I want to use the Mini-Profiler with EF and call

MvcMiniProfiler.MiniProfilerEF.Initialize();

However, since we don't actually create any of the tables, the dbo.__MigrationHistory and dbo.EdmMetadata tables do not exist. The profiler ends up crashing because they don't exist. Is there any way to make the profiler ignore these EF Code First specific tables? Thanks!

EDIT:

These are the exceptions I get: (They come separately)

Invalid object name 'dbo.__MigrationHistory'.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at MvcMiniProfiler.Data.ProfiledDbCommand.ExecuteDbDataReader(CommandBehavior behavior) in \mvc-mini-profiler\MvcMiniProfiler\Data\ProfiledDbCommand.cs:line 155
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)



Invalid object name 'dbo.EdmMetadata'.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
   at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at MvcMiniProfiler.Data.ProfiledDbCommand.ExecuteDbDataReader(CommandBehavior behavior) in \mvc-mini-profiler\MvcMiniProfiler\Data\ProfiledDbCommand.cs:line 155
   at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)

I started a new MVC 4 project and installed/updated the following NuGet packages:

  • EntityFramework
  • MiniProfiler
  • MiniProfiler.EF

I turned off the database initialization strategy in Code First inside of my database context.

public class EmployeeContext : DbContext
{
    static EmployeeContext()
    {
        Database.SetInitializer<EmployeeContext>( null ); // must be turned off before mini profiler runs
    }

    public IDbSet<Employee> Employees { get; set; } 
}

The mini profiler is working properly. I created the one table database by hand.

Turning off the database initializer in the static constructor is important. If you do it elsewhere then it's possible that the mini profiler code runs before your code and hence the queries to the __MigrationHistory table that shouldn't be occurring at all.

What is the recommended way to build functionality similar to Stackoverflow's "Inbox"?

11 votes

I have an asp.net-mvc website and people manage a list of projects. Based on some algorithm, I can tell if a project is out of date. When a user logs in, i want it to show the number of stale projects (similar to when i see a number of updates in the inbox).

The algorithm to calculate stale projects is kind of slow so if everytime a user logs in, i have to:

  1. Run a query for all project where they are the owner
  2. Run the IsStale() algorithm
  3. Display the count where IsStale = true

My guess is that will be real slow. Also, on everything project write, i would have to recalculate the above to see if changed.

Another idea i had was to create a table and run a job everything minutes to calculate stale projects and store the latest count in this metrics table. Then just query that when users log in. The issue there is I still have to keep that table in sync and if it only recalcs once every minute, if people update projects, it won't change the value until after a minute.

Any idea for a fast, scalable way to support this inbox concept to alert users of number of items to review ??

The first step is always proper requirement analysis. Let's assume I'm a Project Manager. I log in to the system and it displays my only project as on time. A developer comes to my office an tells me there is a delay in his activity. I select the developer's activity and change its duration. The system still displays my project as on time, so I happily leave work.

How do you think I would feel if I receive a phone call at 3:00 AM from the client asking me for an explanation of why the project is no longer on time? Obviously, quite surprised, because the system didn't warn me in any way. Why did that happen? Because I had to wait 30 seconds (why not only 1 second?) for the next run of a scheduled job to update the project status.

That just can't be a solution. A warning must be sent immediately to the user, even if it takes 30 seconds to run the IsStale() process. Show the user a loading... image or anything else, but make sure the user has accurate data.

Now, regarding the implementation, nothing can be done to run away from the previous issue: you will have to run that process when something that affects some due date changes. However, what you can do is not unnecessarily run that process. For example, you mentioned that you could run it whenever the user logs in. What if 2 or more users log in and see the same project and don't change anything? It would be unnecessary to run the process twice.

Whatsmore, if you make sure the process is run when the user updates the project, you won't need to run the process at any other time. In conclusion, this schema has the following advantages and disadvantages compared to the "polling" solution:

Advantages

  • No scheduled job
  • No unneeded process runs (this is arguable because you could set a dirty flag on the project and only run it if it is true)
  • No unneeded queries of the dirty value
  • The user will always be informed of the current and real state of the project (which is by far, the most important item to address in any solution provided)

Disadvantages

  • If a user updates a project and then upates it again in a matter of seconds the process would be run twice (in the polling schema the process might not even be run once in that period, depending on the frequency it has been scheduled)
  • The user who updates the project will have to wait for the process to finish

Changing to how you implement the notification system in a similar way to StackOverflow, that's quite a different question. I guess you have a many-to-many relationship with users and projects. The simplest solution would be adding a single attribute to the relationship between those entities (the middle table):

Cardinalities: A user has many projects. A project has many users

That way when you run the process you should update each user's Has_pending_notifications with the new result. For example, if a user updates a project and it is no longer on time then you should set to true all users Has_pending_notifications field so that they're aware of the situation. Similarly, set it to false when the project is on time (I understand you just want to make sure the notifications are displayed when the project is no longer on time).

Taking StackOverflow's example, when a user reads a notification you should set the flag to false. Make sure you don't use timestamps to guess if a user has read a notification: logging in doesn't mean reading notifications.

Finally, if the notification itself is complex enough, you can move it away from the relationship between users and projects and go for something like this:

Cardinalities: A user has many projects. A project has many users. A user has many notifications. A notifications has one user. A project has many notifications. A notification has one project.

I hope something I've said has made sense, or give you some other better idea :)

Can this MVC code be refactored using a design pattern?

7 votes

I've got controller code like this all over my ASP.NET MVC 3 site:

[HttpPost]
public ActionResult Save(PostViewModel viewModel)
{
   // VM -> Domain Mapping. Definetely belongs here. Happy with this.
   var post = Mapper.Map<PostViewModel, Post>(viewModel);

   // Saving. Again, fine. Controllers job to update model.
   _postRepository.Save(post);

   // No. Noooo..caching, thread spawning, something about a user?? Why....
   Task.Factory.StartNew(() => {
       _cache.RefreshSomeCache(post);
       _cache2.RefreshSomeOtherCache(post2);
       _userRepository.GiveUserPoints(post.User);
       _someotherRepo.AuditThisHappened();
   });

   // This should be the 3rd line in this method.
   return RedirectToAction("Index");
}

Basically, i'm referring to the code in the threading block. All things need to happen, but the user doesn't need to wait for them (good case for a background thread, right?).

Just to be clear, i use caching (regular ASP.NET data cache) all over the site, and most of this has a "no expire" cache policy, so i manually evict it when required (like the above).

And the user part is basically giving user rep for doing something (like Stack).

So let's recap: we have caching, user reputation handling, auditing, all in one. Doesn't really belong in one spot does it. Hence the problem with the current code, and the problem with trying to figure out how to move it away.

The reason i want to refactor this is for a few reasons:

  1. Difficult to unit test. Multithreading and unit testing doesn't really play nice.
  2. Readability. It's hard to read. Messy.
  3. SRP. Controller doing/knowing too much.

I solved 1) by wrapping the thread spawning code into an interface, and just mocking/faking that out.

But i would like to do some kind of pattern, where my code could look like this:

[HttpPost]
public ActionResult Save(PostViewModel viewModel)
{
   // Map.
   var post = Mapper.Map<PostViewModel, Post>(viewModel);

   // Save.
   _postRepository.Save(post);

   // Tell someone about this.
   _eventManager.RaiseEvent(post);

   // Redirect.
   return RedirectToAction("Index");
}

Basically, putting the onus on "something else" to react, not the controller.

I've heard/read about Tasks, Commands, Events, etc but have yet to see one implemented in the ASP.NET MVC space.

First thoughts would tell me to create some kind of "event manager". But then i thought, where does this go? In the domain? Well then how does it handle interactions with the cache, which is an infrastructure concern. And then threading, which is also an infrastructure concern. And what if i want to do is synchronously, instead of async? What makes that decision?

I don't want to have to just pile all this logic somewhere else. It ideally should be re factored into manageable and meaningful components, not shifted responsbility, if that makes sense.

Any advice?

First thoughts would tell me to create some kind of "event manager". But then i thought, where does this go? In the domain?

It's the way I solve the problem. I see the event manager as infrastructure. But the actual events belongs in the domain.

Well then how does it handle interactions with the cache, which is an infrastructure concern. And then threading, which is also an infrastructure concern. And what if i want to do is synchronously, instead of async? What makes that decision?

Async is nice, but makes transaction handling complex. If you use an IoC container you already have a well defined scope and a transaction which can be used during the event propagation.

imho it's up to the subscriber to schedule/thread it's task if it knows that it's event handling will take time.

Proposed solution:

Use your IoC container to publish the events. I would let the repository publish the events (either PostUpdated or EntityUpdated depending on what you want to do with the event) rather than the controller (to reduce code duplication).

I've made an IoC implementation for autofac which allows you to:

DomainEventDispatcher.Current.Dispatch(new EntityUpdated(post));

Subscription:

public class CacheService : IAutoSubscriberOf<EntityUpdated>
{
    public void Handle(EntityUpdated domainEvent) {};
}

https://github.com/sogeti-se/Sogeti.Pattern/wiki/Domain-events

Typical usage

  1. Implement IServiceResolver (for your container)
  2. Assign it: ServiceResolver.Assign(new yourResolver(yourContainer))
  3. Use as described here.

Does the standard Html.DisplayTextFor() no HTML encoding?

7 votes

We are currently dealing with some XSS issues on one of our ASP.NET MVC projects. I found two issues - the first one has to do with our request validation pattern. The attacker could now use this security hole to drop some bad content in our database.

The second issue is how we display this content and we use the Html.DisplayTextFor method and it seems to be "broken".

Just create a new MVC 3 WebApp, put this in the HomeController:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Message = "<SCRIPT/XSS SRC=\"htpp://ha.ckers.org/css.js\">";

        User foo = new User();
        foo.Name = "<SCRIPT/XSS SRC=\"htpp://ha.ckers.org/css.js\">";

        return View(bla);
    }

    public ActionResult About()
    {
        return View();
    }
}

public class User
{
    public string Name { get; set; }
} 

The View:

@Html.TextBoxFor(m => m.Name) <br/> ||| <-- will be encoded

@Html.Encode(ViewBag.Message)<br/> ||| <-- will be double encoded

@Model.Name <br/> ||| <-- will be encoded 

@Html.DisplayTextFor(m => m.Name) <-- no encoding
<br/> ||| 

Output of the DisplayTextFor will be the whole string <script xss="" src="htpp://ha.ckers.org/css.js">

Question is: Bug, feature or am I using it wrong?

Html.DisplayTextFor is really for interacting with the [DisplayFormat] attribute (see MSDN).

So if you're using it with unsafe values, you have to be aware of this and use [DisplayFormat(HtmlEncode = true)] on your property.

Edit: Looks like the HtmlEncode property isn't actually enforced by DataAnnotationsModelMetadataProvider (and DisplayTextFor).

Is an ASP.net MVC View a "class"?

7 votes

...before everything, I'm doing this out of curiosity only. Nothing real-world application here, but just for knowledge and tinkering about...

ASP.NET Views have properties like Model and ViewData and even has methods as well.

You can even use @Using just like a regular class.cs file.

I know that it is of type WebPageView<TModel>

My main question is: is it a class?

It should be because it's a type, but..

I should be able to also do this then (Razor engine):

@{
   public class Person
   {
       //etc...
   }

   var p = new Person();
}

<span>@p.Name</span>

However I can't.. why?

note: currently a C#, ASP.net beginner.

You can't do it because Razor markup is compiled into a sequence of statements inside a method within the generated class derived from WebViewPage or WebViewPage<TModel>

The more important question though, is why would you want to do this? Instead prefer to keep Razor free of this kind of logic - it's job should be to produce layout, not do any kind of business logic, or business data transformation. Do all the heavy lifting in your action method and deliver a Model that describes the data required to render the layout in a format that requires only simple Razor markup to process.

There are quite a few tutorials a round that describe how to approach MVC and Razor. I dug up this one that is brief but does a reasonable job of covering an end-to-end story that might help you get the idea. It does include using EF to get data as well which might be more that you were bargaining for - but it's worth a read to get the full picture of how a whole architecture hangs together: http://weblogs.asp.net/shijuvarghese/archive/2011/01/06/developing-web-apps-using-asp-net-mvc-3-razor-and-ef-code-first-part-1.aspx

MVC - is there a nice way to bundle controls with their respective javascript?

6 votes

I'm pretty new to MVC and I can't decide on the best way to store cshtml files and their respective javascript code. Some JS code in my project needs to run globally, but most of it is entirely tied to specic views or partial views.

If I put the javascript in the views, I get a mess of inline uncacheable javascript, if I put it in one central file, I lose modularity.

I heard that in MVC4 there are going to be minification features, is there something I can do with MVC3 that will allow me to choose in the Views which javascripts to include and then group them and minify them automatically? (maybe even in groups?)

Cassette it's essentially the same thing as the upcoming MVC4 bundles.

In your view page, you can reference scripts and stylesheets using Cassette's Bundles helper class.

@{
    Bundles.Reference("Scripts/jquery.js");
    Bundles.Reference("Scripts/page.js");
    Bundles.Reference("Styles/page.css");
}
<!DOCTYPE html>
    <html>
...

In addition, Cassette has native support for Less and CoffeScript. It has also support for HTML Templates, if you are interested in client side MVC frameworks like Knockout.js or Backbone.js.

Still you have to choose how to group your content. As the official documentation is suggesting, probably the best choice is to treat bundles as units of deployment.

Keep in mind that a bundle is a unit of deployment. If any asset in a bundle changes, then the entire bundle has to be downloaded again by web browsers. So perhaps group shared code into a bundle and put page scripts into their own bundles.

Is usage of HTML-5 data-* attributes broken in ASP.NET MVC 4 (beta)?

6 votes

According to this question, I am supposed to be able to write something like this:

@Html.ActionLink( "Delete", "Delete", "Message", new { data_id=id, @class="delete" } )

or as a happy T4MVC user can do:

@Html.ActionLink( "Delete", MVC.Message.Actions.Delete(), new { data_id=id, @class="delete" } )

And get the underscore in "data_id" replaced during rendering:

<a href="/message/delete" class="delete" data-id="42">Delete</a>

However, this seems not to work in the MVC 4 beta. Anyone else seeing this problem?

Is it an intentional change, and if so, what should I do instead?

UPDATE - HOW TO FIX (MANUALLY)

I've applied the following changes to the T4MVC.tt file, which fixes the problem in the generated code:

public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, ActionResult result, object htmlAttributes, string protocol = null, string hostName = null, string fragment = null) {
    //was: return ActionLink(htmlHelper, linkText, result, new RouteValueDictionary(htmlAttributes), protocol, hostName, fragment);
    return htmlHelper.RouteLink(linkText, null, protocol, hostName, fragment, result.GetRouteValueDictionary(), HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}

UPDATE 2 - FIX AVAILABLE

David Ebbo was lightning fast at responding to the reported issue and has already merged the above fix into T4MVC.

UPDATE 3 - FIX THE FIX

Quite embarassingly, the original fix submitted did in fact not work, as it still called an invalid overload. I've now modified the code to do the same as MVC does internally (using their helper method), and notified David to have it included in T4MVC. Grab 2.6.70 from codeplex or update using NuGet when its released, probably shortly.

Try

@Html.ActionLink( "Delete", "Delete", "Message", null, new { data_id=id, @class="delete" } )

I think that becuase of all the overloads it is assuming your 4th parameter is the routeValues parameter.

What c# classes and functions can be used in razor?

5 votes

Using ASP.NET MVC can be used the view engine Razor.

Razor let you use c# code after the @ sign.

As example

@if (Model.Category == "watersports")
{
    <p>Splash!!</p>
}

Furthermore you can use something like @DateTime.Now for get the current time. My question is: what functions can be used? From where Razor import them?

Any public class. They get imported with @using MyNamespace. You can also import them in the config file

<system.web.webPages.razor>

element.

Why some asp.net developers encrypt ConnectionStrings?

5 votes


I seen some asp.net developers encrypt ConnectionStrings that was included in separate config file.
Why they did that ? I know that config files are unreadable from the client side/browser! Is it possible to access to this kind of files ?

You can't rule out that the web box is compromised. Also, you don't want the web admins to know passwords to databases.

RavenDB Embedded on GoDaddy - Application_Start firing multiple times

5 votes

I'm using RavenDB Embedded on my MVC3 application. Locally in IIS Express, the whole app works fine.

However, hosted at GoDaddy, I'm seeing Application_Start fire multiple times. This is problematic, because Raven tries to initialize multiple times, which throws the "Cannot access file, the file is locked or in use" exception.

Here's my Global.asax.cs code:

private static IDocumentStore raven;

protected void Application_Start()
{
   AreaRegistration.RegisterAllAreas();

   RegisterGlobalFilters(GlobalFilters.Filters);
   RegisterRoutes(RouteTable.Routes);

   // Initialize the Raven store just once.
   raven = new EmbeddableDocumentStore { ConnectionStringName = "RavenDB" };
   raven.Initialize(); // EXCEPTION THROWN HERE: "cannot access file, the file is locked"
}

protected void Application_End()
{
   raven.Dispose();
}

For the first computer to access my web app, it works. For the 2nd, and 3rd, etc. machines to access my web app, I get the exception. It's like GoDaddy starts the web app for every unique visitor to the site.

Bottom line: GoDaddy seems to be calling Application_Start multiple times, or at least, calling Application_Start for every unique IP address that accesses the application.

Any idea what's going on?

I was unable to get RavenDB embedded working with GoDaddy, as GoDaddy kept recycling my IIS app for some reason (raven changes?) and this caused Raven to bomb as it resulted in multiple initializations of the embedded database.

What I ended up doing was keeping my GoDaddy shared hosting (cheap), but moving my database to RavenHQ on AppHarbor (free for 25MB database).

End result? I only had to make a connection string change, going from Raven Embedded to full Raven on AppHarbor. My app just worked, GoDaddy stopped recycling my app, and all is well.

c# add using declaration for namespace to all classes

5 votes

Is it possible to add a using declaration to a namespace globally?

For example, I want all of my classes under the "MyApp.Models" namespace to include the namespace System.Linq.Dynamic.

In asp.net you can do this for view by adding the namespace in the web.config. Is there a way to do this for class files as well?

No. It is not possible to add a global using declaration to a C# project. You must specify the complete set of using in each .cs file

Adding Areas to an MVC application - any gotchas?

5 votes

I have an ASP.net MVC application that has been in Production for a while. I would like to add a new Admin section to the application which I wanted to do by creating a new Area. I'm just curious what sorts of things I might need to be aware of when adding this new area.

Specifically:

  1. Is there any existing functionality that is likely to break by adding the new Area?
  2. What is the best way to make an Area restricted to a certain group? Base controller class?
  3. Any other things (common mistakes, etc.) that I need to be aware of that adding a new Area will affect?

One thing to be careful of is naming collisions - if you have 2 controllers with the same name but in different areas you need to add namespaces, as described here: http://haacked.com/archive/2010/01/12/ambiguous-controller-names.aspx

To restrict the admin area to a certain group, you could use the Authorize attribute with Roles on the Admin controller(s), as desribed here: ASP.NET MVC 3 - How to restrict areas in an efficient way?

ASP.net MVC View's Model vs ViewData.Model?

5 votes

I'm learning asp.net mvc and found something interesting:

It seems that I can't explicitly define a View's Model from within the View with error message saying that it has no setter.

@{ this.Model = "Hello" } //error

Then I looked at the source code in WebViewPage.cs and a View's Model property is actually like this:

public object Model { get { return ViewData.Model; } }

Thus the error.

But it's interesting how I can do this: @{ ViewData.Model = "hello"; } and actually be able to use the @model statement, resulting to "hello"

I think I'm looking too much into it, but why is this so?

beginner at C# and ASP.NET

The rule is Separation of Concern...In MVC, a Controller supplies a Model to a View and it will always be the controller that can set/assign a Model to a view....which the Views can use...this is by design...play by rules is what I would say...and If you are learning MVC its great and I would strongly recommend you to read

Stevens Sandersons MVC book