Best asp.net-mvc-3 questions in April 2012

MVC routes with special characters

6 votes

I'm trying to support some legacy urls, and map them to controller actions. The URLs look like this:

/~Home+Office~Note+Pads.html

Here's my route:

routes.MapRoute(
    "LegacyCategory",
    "{path}.html",
    new { controller = "LegacyCI", action = "Index", }
);

Here's the (beginnings of) my controller to deal with them:

public class LegacyCIController : Controller {
    public ActionResult Index(string path) {
        if (path == "~Address+Labels") {
            return RedirectToAction("Display", "Category", new { id = "AddressLabels" });
        }       
        return RedirectToAction("Index", "Category"); 
    }
}

If I set a breakpoint in LegacyCIController, and I set my start page to XXX.html, the breakpoint hits (and fails the if) and life is good. But when I try to set the start page to ~Address+Labels.html, no breakpoint is hit, and Chrome just pukes and shows me a page that says "oops, this page appears to be broken".

I'm running this page through IIS 7 on my machine, not Visual Studio.

Is this URL so malformed that a regular MVC route can't even handle it, or am I doing something else wrong?

By default IIS7 blocks URLs (error 404.11) with a + in the path, you can override this by turning on allowDoubleEscaping in web.config:

  <system.webServer>
    <security>
      <requestFiltering allowDoubleEscaping="true">
      </requestFiltering>
    </security>
  </system.webServer>

However, as explained on the IIS blog this option opens a potential security hole, so be a little careful while using it:

http://blogs.iis.net/thomad/archive/2007/12/17/iis7-rejecting-urls-containing.aspx

How can I write an MVC3/4 application that can both function as a web API and a UI onto that API?

5 votes

My title sums this up pretty well. My first though it to provide a few data formats, one being HTML, which I can provide and consume using the Razor view engine and MVC3 controller actions respectively. Then, maybe provide other data formats through custom view engines. I have never really worked in this area before except for very basic web services, very long ago. What are my options here? What is this Web API I see linked to MVC4?

NOTE: My main HTML app need not operate directly off the API. I would like to write the API first, driven by the requirements of a skeleton HTML client, with a very rudimentary UI, and once the API is bedded down, then write a fully featured UI client using the same services as the API but bypassing the actual data parsing and presentation API components.

I had this very same thought as soon as the first talk of the Web API was around. In short, the Web API is a new product from the MS .NET Web Stack that builds on top of WCF, OData and MVC to provide a uniform means of creating a RESTful Web API. Plenty of resources on that, so go have a Google.

Now onto the question..

The problem is that you can of course make the Web API return HTML, JSON, XML, etc - but the missing piece here is the Views/templating provided by the Razor/ASPX/insertviewenginehere. That's not really the job of an "API".

You could of course write client-side code to call into your Web API and perform the templating/UI client-side with the mass amount of plugins available.

I'm pretty sure the Web API isn't capable of returning templated HTML in the same way an ASP.NET MVC web application can.

So if you want to "re-use" certain portions of your application (repository, domain, etc), it would probably be best to wrap the calls in a facade/service layer of sorts and make both your Web API and seperate ASP.NET MVC web application call into that to reduce code.

All you should end up with is an ASP.NET MVC web application which calls into your domain and builds templated HTML, and an ASP.NET Web API application which calls into your domain and returns various resources (JSON, XML, etc).

If you have a well structured application then this form of abstraction shouldn't be a problem.

how to deploy MVC3 WebApp to windows Azure

5 votes

How is it possible to deploy MVC3 web roles to windows Azure? Most of the tutorials seems done on deploying ASP.NET web roles than the MVC3 one.

can any one give me a link/hint?

Way back in the old days, MVC3 wasn't supported out-of-the-box because the appropriate DLLs needed to be manually added by you (or installed as a startup task). These days, the MVC dll's are all there using the MVC3 template, so there's no difference in what you'd need to do, between asp.net and asp.net mvc deployment. The basic Web Roles and Worker roles are just Windows 2008 Server VMs, and the deployment process is the same. The most important part, when starting out, is making sure your connection strings to storage point to "real" storage and not dev storage (such as your diagnostics connection string). Also, session state defaults to using SQLExpress, which isn't running in Windows Azure, so you'll need to either use a SQL Azure database (plus proper connection string) in web.config, or change session state to use Cache (again, a web.config change).

How to do background jobs in an ASP.NET MVC 3 site?

5 votes

I'm currently working on an e-commerce site and there's one feature that i'm not very sure how to implement. Most of the time you just add product(s) to your cart and buy them, that's probably the simplest workflow. What i'm asking is a little different, what if there's a time limit for a product to buy ? I mean some sites give you an exact time limit to buy a product (like Soccer Manager), in those sites you can't hold a product forever, there's a 15 minutes limit for it and if you dont buy in that period, item will be released from your cart. (and most probably someone else will jump on it)

Now, as an ASP.NET MVC programmer i'd love to implement this feature but as i said, i'm not sure how to do it. I think when i add item to cart i need to hold the time (something like ItemAddedAt) and i need to release that item in x minutes so something needs to run x minutes later to release that product. Globally thinking, i think i need a service, when i add an item, i also need to subscribe it to this service and service runs a timer/job in the background. What i dont know/have no experience is this part, how to do that in an ASP.NET MVC project, is there a sample project, article, library or something like that ?

Of course i dont know if my logic is right for this problem, i need some guidance, if possible some source code to work on.

AFAIK there are no standard way to declare/program tasks within an MVC project. The recommended way to accomplish what you want would be to create a new Console Application project within your solution, and use the Windows Task Scheduler to execute every X minutes, releasing any products that have been more than X minutes in any cart.

For this to work, you will need to reference your MVC project from the new one (to get access to all the models) or, even better, create a Class Library project, move your Model/database classes there, and reference it from the MVC and Console projects.


All that being said, there is actually a small "hack" that can be used to get programmed tasks in an MVC project. You can use the following code:

HttpContext.Current.Cache.Add("Task", "1", null, 
            DateTime.MaxValue, TimeSpan.FromMinutes(5), 
            CacheItemPriority.Normal, new CacheItemRemovedCallback(CheckCarts));

That line, that could be called, for example, from the Global.asax, would add a "Task" entry to the cache. The value stored ("1") is not important, the important thing is that the cache entry expires in five minutes and, when expired, calls the "CheckCarts" method (defined in the Global.asax, or in the class were you execute this code).

public void CheckCarts(string key, object value, CacheItemRemovedReason reason) {
     // Insert your code here to check for expired carts
     (...)

     // We add the entry again to the cache, so that this method will be called again in 5 minutes.
     HttpContext.Current.Cache.Add("Task", "1", null, 
            DateTime.MaxValue, TimeSpan.FromMinutes(5), 
            CacheItemPriority.Normal, new CacheItemRemovedCallback(CheckCarts));
}

When the cache expires, the CheckCarts method is called, your code does whatever it has to do, and in the end adds itself to the Cache again, to be called in another 5 minutes.

Difference Between Static or NoneStatic Methods in ASP.NET MVC

4 votes

I need a method that return me some parameters in controllers this is implementation of it:

    public List<Parameter> GetParameters(FormCollection collection) {

        List<Parameter> parameters = new List<Parameter>();
        List<string> parameterNames = new List<string>();

        //Get Parameters Names and Values

        return parameters;
    }

I use this method in all of controllers, So I think about 3 option that I have to define it:

1-For any controller class define it in that controller like this:

public class ProductController : Controller {

   public List<Parameter> GetParameters(FormCollection collection) {

   //

    }
  }

2-Define it in static class as static method:

public static class GeneralMethods {

   public static List<Parameter> GetParameters(FormCollection collection) {

   //

    }
  }

3-Define it as a None Static :

public class GeneralMethods {

   public List<Parameter> GetParameters(FormCollection collection) {

   //

    }
  }

which one is better? which one have better performance? or any other option for define methods that used in many controllers? what is your suggestion?

There will be no performance impact in any of the three. (Though last approach will create separate object each time,it will be gracefully handled by GC).

approach 1: NO, as a standard practice we should not duplicate the code.

approach 2: YES, if your method depends only on the input parameter.

approach 3: YES, if you need to set up some instance variable and your method depends on them.

suggested approach: (approach 1+ approach 3) If this method is common to all of your controller (or most), declare a base controller with this method and inherit all other controller from it.

Static methods will not be a problem as any variable declared with in a method are with in scope of the method.

MVC3 binding for a json nested array

4 votes

I have a simple javascript array. it's declared like this:

coords = []

and everytime a user clicks on an image, I do something like this:

coords.push([x,y])

so I end up with something like this: (in javascript)

[[342,144],[477,99],[632,148],[529,162]]

but I don't know what to bind it to in the controller method... I've tried

List<List<int>>, int[][], int[,]

none of them seem to work. It only works when I use string.

This is the code I'm using to send it to the server:

$.ajax({
    type: "POST",
    url: "/home/SaveCoords",
    data: { coords: JSON.stringify(coords) }
}).done(function (msg) {
    alert("Data Saved: " + msg);
});

And this is the code I use on the controller

[HttpPost]
public ActionResult SaveCoords(string coords)
{
    return Json("Hello", JsonRequestBehavior.AllowGet);
}

Help?

You should set request content type to application/json, and change data accordingly.

This is the working example:

    $.ajax({
        type: "POST",
        url: "/home/SaveCoords",
        contentType : 'application/json',
        data: JSON.stringify(coords)
    }).done(function (msg) {
        alert("Data Saved: " + msg);
    });

And server

    public ActionResult SaveCoords(int[][] coords)
    {
        return View();
    }