Best asp.net-mvc questions in April 2011

ASP.NET MVC3 and Entity Framework Code first architecture

7 votes

My previous question made me think again about layers, repository, dependency injection and architectural stuff like this.

My architecture now looks like this:
I am using EF code first, so I just made POCO classes, and context. That creates db and model.
Level higher are business layer classes (Providers). I am using different provider for each domain... like MemberProvider, RoleProvider, TaskProvider etc. and I am making new instance of my DbContext in each of these providers.
Then I instantiate these providers in my controllers, get data and send them to Views.

My initial architecture included repository, which I got rid of because I was told that it just adds complexity, so why I don't just use EF only. I wanted to did that.. working with EF directly from controllers, but I have to write tests and it was a bit complicate with real database. I had to fake - mock data somehow. So I made an interface for each provider and made fake providers with hardcoded data in lists. And with this I got back to something, where I am not sure how to proceed correctly.

These things starts to be overcomplicated too quickly... many approaches and "pattterns"... it creates just too much noise and useless code.

Is there any SIMPLE and testable architecture for creating and ASP.NET MVC3 application with Entity Framework?

If you want to use TDD (or any other testing approach with high test coverage) and EF together you must write integration or end-to-end tests. The problem here is that any approach with mocking either context or repository just creates test which can test your upper layer logic (which uses those mocks) but not your application.

Simple example:

Let's define generic repository:

public interface IGenericRepository<TEntity> 
{
    IQueryable<TEntity> GetQuery();
    ...
}

And lets write some business method:

public IEnumerable<MyEntity> DoSomethingImportant()
{
    var data = MyEntityRepo.GetQuery().Select((e, i) => e);
    ...
}

Now if you mock the repository you will use Linq-To-Objects and you will have a green test but if you run the application with Linq-To-Entities you will get an exception because select overload with indexes is not supported in L2E.

This was simple example but same can happen with using methods in queries and other common mistakes. Moreover this also affects methods like Add, Update, Delete usually exposed on repository. If you don't write a mock which will exactly simulate behavior of EF context and referential integrity you will not test your implementation.

Another part of story are problems with Lazy loading which can also hardly be detected with unit tests against mocks.

Because of that you should also introduce integration or end-to-end tests which will work against real database using real EF context ane L2E. Btw. using end-to-end tests is required to use TDD correctly. For writing end-to-end tests in ASP.NET MVC you can WatiN and possibly also SpecFlow for BDD but this will really add a lot of work but you will have your application really tested. If you want to read more about TDD I recommend this book (the only disadvantage is that examples are in Java).

Integration tests make sense if you don't use generic repository and you hide your queries in some class which will not expose IQueryable but returns directly data.

Example:

public interface IMyEntityRepository
{
    MyEntity GetById(int id);
    MyEntity GetByName(string name); 
}

Now you can just write integration test to test implementation of this repository because queries are hidden in this class and not exposed to upper layers. But this type of repository is somehow considered as old implementation used with stored procedures. You will lose a lot of ORM features with this implementation or you will have to do a lot of additional work - for example add specification pattern to be able to define query in upper layer.

In ASP.NET MVC you can partially replace end-to-end tests with integration tests on controller level.

Edit based on comment:

I don't say that you need unit tests, integration tests and end-to-end tests. I say that making tested applications require much more effort. The amount and types of needed tests is dependent on the complexity of your application, expected future of the application, your skills and skills of other team members.

Small straighforward projects can be created without tests at all (ok, it is not a good idea but we all did it and at the end it worked) but once a project passes some treshold you can find that introducing new features or maintaining the project is very hard because you are never sure if it breaks something which already worked - that is called regression. The best defence against regression is good set of automated tests.

  • Unit tests help you to test method. Such tests should ideally cover all execution paths in the method. These tests should be very short and easy to write - to complicated part can be to set up dependencies (mocks, faktes, stubs).
  • Integration tests help you to test functionality accross multiple layers and usually accross multiple processes (application, database). You don't need to have them for everything, it is more about experience to select where they are helpful.
  • End-to-end tests are something like validation of use case / user story / feature. They should cover whole flow of the requirement.

It is not needed to test a feture multiple times - if you know that the feature is tested in end-to-end test you don't need to write integration test for the same code. Also if you know that method has only single execution path which is covered by integration test you don't need to write unit test for it. This works much better with TDD approach where you start with a big test (end-to-end or integration) and go deeper to unit tests.

Depending on your developement approach you don't have to start with multiple types of test from beginning but you can introduce them later as your application will become more complex. The exception is TDD/BDD where you should start to use at least end-to-end and unit tests before you even write single line of other code.

So you are asking the wrong question. The question is not what is simpler? The question is what will help you at the end and what complexity fits your application? If you want to have easily unit tested application and business logic you should wrap EF code to some other classes which can be mocked. But in the same time you must introduce other type of tests to ensure that EF code works.

I can't say you what approach will fit your environment / project / team / etc. But I can explain example from my past project:

I worked on the project for about 5-6 months with two collegues. The project was based on ASP.NET MVC 2 + jQuery + EFv4 and it was developed in incremental and iterative way. It had a lot of complicated business logic and a lot of complicated database queries. We started with generic repositories and high code coverage with unit tests + integration tests to validate mapping (simple tests for inserting, deleting, updating and selecting entity). After few months we found that our approach doesn't work. We had more then 1.200 unit tests, code coverage about 60% (that is not very good) and a lot of regression problems. Changing anything in EF model could introduce unexpected problems in parts which were not touched for several weeks. We found that we are missing integration tests or end-to-end tests for our application logic. The same conclusion was made on a parallel team worked on another project and using integration tests was considered as recommendation for new projects.

How to Generate absolute urls with https in MVC3?

6 votes

Hello,

I am using MVC3 and am trying to serve content from https, the problem is that when I call Url.Content the files are still served from http using a relative url. I thought this problem was addressed in MVC3 but i can't seem to find any solution. Does anybody know if this issue is inherently solved in MVC3 and how to accomplish it or do I need to create my own helper methods to generate absolute Urls based on protocol?

You can probably implement your own solution using VirtualPathUtility.ToAbsolute. Probably something like this:

public static class UrlHelperExtension {
  public static string Absolute(this UrlHelper url, string relativeOrAbsolute) {
    var uri = new Uri(relativeOrAbsolute, UriKind.RelativeOrAbsolute);
    if (uri.IsAbsoluteUri) {
      return relativeOrAbsolute;
    }
    // At this point, we know the url is relative.
    return VirtualPathUtility.ToAbsolute(relativeOrAbsolute);
  }
}

which you would use like:

@Url.Absolute(Url.Content("~/Content/Image.png"))

(Didn't test this myself, feel free to play around to make it work right.)

This helps to you to generate absolute URLs for your content files. In order to change the scheme of the resulting URLs, you can create an additional extension method that manipulates the scheme of the given URLs so that they are HTTPS, or something else.

As Khalid points out in the comments, similar extension methods are already available in various open-source projects which you can make use of (given that the license permits). An example one can be found here.

Is it bad practice to have a ViewModel with a propety typed as another ViewModel in ASP.NET MVC

6 votes

Hey guys,

Would it be considered bad practice to have a viewmodel that has a property of another view model?...as in:

public class PersonViewModel
{
     public PersonJobViewModel Peron { get; set;}
     //other properties here...
}

EDIT

A little more about my particular situation:

I have a view model that currently contains 2 domain classes. I pass this viewmodel to a view that loads 2 partials views(one for each domain class in the viewmodel)

So with this I end up passing pure domain models directly into the partial views.

My thinking is that I can make a view model for each domain model that go to the partials...and then wrap those 2 in another viewmodel that gets passed to my parent...

or is there a better way to accomplish this?

No, it's not bad at all. It's perfectly fine code. It allows you to reuse portions of view models between different views.

How to run a script after client validation in asp.net mvc

5 votes

I am disabling my submit buttons when submitting a form, for preventing the user to submit the form multiple times.

$(function ()
{
    $("form").submit(function ()
    {
        $(":submit", this).attr("disabled", "disabled");
    });
});

But if the client validation fails I want to enable the button again. I am using asp.net mvc unobtrusive client validation

You can use the jQuery One event as detailed in this answer.

Most solutions to this issue revolve around testing $("form").valid() - you could probably use this in your function to determine whether to disable the submit button.

Using port 80 with IIS Express inside of VS2010

5 votes

I've got an app that I am trying to run on my dev system under IIS Express from VS2010 that I need to use port 80 for, but I can't get it to work. I've looking up information talking about port 80 being reserved. http://learn.iis.net/page.aspx/1005/handling-url-binding-failures-in-iis-express/

But even after doing that I still get an error from vs2010 that says "Unable to launch the IIS Express Web server. Port '80' is in use."

I don't know what else to try. I've used Process Hacker to track down port 80 and it seems to be used by System running on process ID 4, which is the NT Kernel and System process. I don't know if that would prevent me from using the port though. I thought maybe that was a result of http.sys holding that port so nothing else could use it?

I did managed to get IIS Express to run on port 80 by modifying the default binding of the C:\Users\[MyUser]\Documents\IISExpress\config\applicationhost.config file, and while I can start IIS Express manually this way, VS then gets an error because a binding already exists on that port. So I change it back to 8080, create the virtual directory using the button within VS2010 (which I'm guessing is the same as entering a site binding) but I still get an error when I go to debug the application. Is there something hardcoded in VS2010 that won't let it start IIS Express on port 80?

UPDATE & FIX: Ok, so I found a few more things to check and I did resolve my problem but not completely. One post suggested making sure I did not have SQL reporting services installed as it can monitor on port 80, I used to have it installed but not anymore and was not the problem I was encountering. I did however realize that I have WebDeploy installed. It was bundled with the VS2010 SP1 bundle from the Web Platform Installer. This is fine as I do want the client tools from WebDeploy, but it also installed the agent on my system which was monitoring on port 80. I went to my list of services and stopped the Web Deploy Agent Service. Soon as I did this I can now use port 80 for IIS Express from within VS2010.

New Issue related to running on port 80 in IIS Express However my application is an MVC3 App, and I've run into a problem because the MVC3 isn't capturing my request at all, so It's not firing my controller actions or anything like that, but a txt file in the root of my app can be reached so I know it's my site that IIS Express is serving up. Anyone have any issues running an MVC3 (I don't know if it's exclusive to MVC3 or not) in IIS Express on port 80?

Just posting my own answer for this problem so I can mark the question as answered. Check http://learn.iis.net/page.aspx/1005/handling-url-binding-failures-in-iis-express/ Disable the Web Deploy Agent service if you have it installed.

How do I use Google Maps geocoder.getLatLng() and store its result in a database?

5 votes

Hey everybody! Im trying to use getLatLng() to geocode a list of postal/zip codes and store the generated point in the database to be placed on a map later. This is what I've got so far:

 $(".geocodethis").click(function () {
    var geocoder = new GClientGeocoder();
    var postalCode = $(this).siblings(".postal").val();
    var id = $(this).siblings(".id").val();

    geocoder.getLatLng(postalCode, function (point) {
        if (!point) {
            alert(postalCode + " not found");
        } else {
            alert(point);
            var serializedPoint = $.param(point);                
            //Geocode(id, point);
        }
    });

});

function Geocode(id, point) {
    alert(point);
    $.post("/Demographic/Geocode/" + id, point, function () {
        alert("success?");
    });
}

but I'm getting this.lat is not a function in my error console when i try to serialize the point object or use it in $.post()

From my research, I understand that geocoder.getLatLng() is asynchronous, how would that affect what I'm trying to do? I'm not running this code in a loop, and I'm trying to post the point using the anonymous callback function.

How can I save the information from point to use later?

Update

Creating a marker and trying to post that still results in the this.lat is not a function in the error console.

$(".geocodethis").click(function () {
        var geocoder = new GClientGeocoder();
        var postalCode = $(this).siblings(".postal").val();
        var id = $(this).siblings(".id").val();

        geocoder.getLatLng(postalCode, function (point) {
            if (!point) {
                alert(postalCode + " not found");
            } else {
                alert(point);
                var marker = new GMarker(point);

                $.post("/Demographic/Geocode/" + id, marker, function () {
                    alert("success?");
                });
            }
        });

    });

** Another Update **

I really need to save the geocoded address for later, even if I store the latitude/longitude values in my database and remake the marker when I'm ready to put it onto a map. Again, serializing or posting - seemingly using the point in any way other than in google maps functions gives the this.lat is not a function exception in my error log.

I'm using asp.net mvc - are there any frameworks out there that would make this easier? I really need help with this. Thanks.

If your stuck for 2 days maybe a fresh v3 start would be a good thing, this snipped does a similair job for me...

          function GetLocation(address) {
          var geocoder = new google.maps.Geocoder();
          geocoder.geocode({ 'address': address }, function (results, status) {
              if (status == google.maps.GeocoderStatus.OK) {
                  ParseLocation(results[0].geometry.location);

              }
              else
                alert('error: ' status);

          });
      }

  }

  function ParseLocation(location) {

      var lat = location.lat().toString().substr(0, 12);
      var lng = location.lng().toString().substr(0, 12);

      //use $.get to save the lat lng in the database
      $.get('MatchLatLang.ashx?action=setlatlong&lat=' + lat + '&lng=' + lng,
            function (data) {
                // fill textboss (feedback purposes only) 
                //with the found and saved lat lng values
                $('#tbxlat').val(lat);
                $('#tbxlng').val(lng);
                $('#spnstatus').text(data);


            });
    }

5 votes

I'm developing an ASP.NET MVC 3 application. I need this application to make use of an API I also need to implement. The API should both be available from ASP.NET MVC controller actions and Ajax. Now it is quite easy to make an API using ASP.NET MVC, but is it possible to use this from other ASP.NET MVC website actions? I guess the WCF is quite easy to use as it is just a service reference.

Other users of the API could be Windows Phone and iPhone.

Update:

Many only sees the API as a place where you consume data, but what about the part where you want to execute commands or do stuff, like add customer or change foo?

You may want to check our new WCF web API that was announced at PDC. We recently released a big upgrade. WCF Web API is designed specifically for allowing you to expose APIs to a range of clients in a pure HTTP manner. It is lightweight, offers a nice configuration story (no configuration files) and also is much easier to test.

You can download the bits at wcf.codeplex.com. It includes various samples, and there is also a set of NuGet packs for getting you started. Search for webapi.all on NuGet.

ASP.NET MVC 3 (Razor) Ajax.ActionLink - What am i doing wrong?

4 votes

Hi Guys,

Trying to have a AJAX action link which when clicked, should do a HttpGet to an action method which returns a PartialViewResult and shoves the HTML into a div.

Here's my View:

<div id="admin-options" class="admin"></div>
@Ajax.ActionLink("Show Admin Options", "ShowOptions", "Post", new { area = "Admin" }, new AjaxOptions { UpdateTargetId = "admin-options", HttpMethod = "GET" })

Here's the action method:

public class PostController : Controller
{
   [HttpGet]
   [Authorize(Roles="Admin")]
   public PartialViewResult ShowOptions()
   {
      return PartialView();
   }
}

Here's the HTML it generates:

<a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" data-ajax-update="#admin-options" href="/Admin/Post/ShowOptions">Show Admin Options</a>

Looks fine to me.

But instead of doing an AJAX call, it does a regular HTTP GET via the browser URL, and redirects to /Admin/Post/ShowOptions.

Obviously im missing something - but what?

Make sure you have the unobstrusive AJAX javascript library included in your page.

<script src="<%=Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")%>" type="text/javascript"></script>

Can ASP.MVC 3 run in a site root and allow other ASP.Net apps to run in subfolders?

4 votes

Can I have an ASP.MVC 3 application running in my site root (a simple CMS to provide MOST site content), and have it co-exist with additional ASP.Net apps (2 Web Forms apps and 1 MVC app) running in subfolders to provide more specialized functionality?

Example:

www.mycompany.com
/             // ASP.MVC 3 App goes here to handle 90% of our page content.
/store/       // Older web forms app to handle our online store.
/survey/      // Older web forms app to provide survey forms.
/locations/   // An ASP.MVC 3 app to render a map with site locations.

I wouldn't mind integrating the 'locations' MVC app with the CMS if necessary, but if they can be separate, it would simplify long term maintenance. Does the root application need to know about the others? (including the other projects as subprojects into the main MVC project in VS.2010?)

As for the 'store' and 'survey' Web Forms apps. They are running .Net 3.5, but we could recompile them to 4.0 if needed. Do the 'store' 'survey' and 'locations' folders need to be virtual folders mapped in with IIS?

Hopefully this example is simplified enough, to find out if it is possible (and how) to integrate applications together with ASP.MVC 3 running in the site root. I'm in a situation where the separate apps must share a domain and pretend to be 1 cohesive site. (They will all share the same HTML template)

Just mark those other applications as Applications in IIS and that will do.

What does WebActivator do?

4 votes

This code was generated for me after added entity framework code-first for SQLCE using NuGet. They did no changes to any other file. The file (SQLCEEntityFramework.cs was created and placed in App_Start folder.

Does this mean it automatically gets executed or something? The same thing happened when I added Ninject for MVC 3. No code was added to the global.ascx file so I have no idea if its plug and play or I have to configure something.

[assembly: WebActivator.PreApplicationStartMethod(typeof(StackTorrents.WebUI.App_Start.SQLCEEntityFramework), "Start")]

According to:

http://haacked.com/archive/2010/05/16/three-hidden-extensibility-gems-in-asp-net-4.aspx

This new attribute allows you to have code run way early in the ASP.NET pipeline as an application starts up. I mean way early, even before Application_Start. This happens to also be before code in your App_code folder (assuming you have any code in there) has been compiled. To use this attribute, create a class library and add this attribute as an assembly level attribute. A common place to add this would be in the AssemblyInfo.cs class within the Properties folder.

ViewBag.ViewData is null, but possible to expand in debugger?

4 votes

Just came across an interesting effect while debugging a View. The scenario is easy to reproduce - I have a breakpoint in a View, in the Watch window I add ViewBag.ViewData and the value is null. However, if I just add ViewBag and expand the object, I can see the ViewData and it is not null. I can also successfully expand it and see its properties.

Can anyone explain whether it's a bug or what causes this behavior?

ViewBag.ViewData in Watch window

EDIT

ViewBag.ViewData is actually null. E.g. if I have this code in the View:

if (ViewBag.ViewData == null)
{
    <span>ViewBag.ViewData is null</span>
}

it displays the span. So the weird part is that I can expand it in the watch window and see the properties.

EDIT2

In response to @Darin Dimitrov's answer - I tried to reproduce this behavior with a custom test class and I get a RuntimeBinderException when trying to access the private property: 'SomeClass.SomeProperty' is inaccessible due to its protection level:

public class SomeClass
{
    private string SomeProperty;
}

dynamic dynamicObject = new SomeClass();
if (dynamicObject.SomeProperty == null)
{
    Console.WriteLine("dynamicObject.SomeProperty is null");
}

In this case, shouldn't I be getting the same exception when accessing ViewBag.ViewData in the View (the line with if (ViewBag.ViewData == null))?

What you see in the debugger/watch window is the private ViewData property of the ViewBag. When you do the test in the view you obviously have no access to this private field and you get null because there is no corresponding public property.

Now do the following test in the view:

@if (null == ViewBag
         .GetType()
         .GetProperty("ViewData", BindingFlags.Instance | BindingFlags.NonPublic)
         .GetValue(ViewBag, null)
)
{
    <span>ViewBag.ViewData is null</span>
}

and you won't see the span.

Of course all this is very funny but when it comes to writing real world and properly architected ASP.NET MVC applications both ViewData and ViewBag have no place. Those two are my worst enemies in ASP.NET MVC application development.

Conclusion: always use view models and strongly typed views and have fun.