Best asp.net-mvc questions in April 2012

What is the most efficient way to store / retrieve items in asp.net httpContext.Cache

11 votes

I have a website where I cache a lot of info. I am seeing conflicting information around storing stuff in the asp.net cache.

For example lets say I have this data structure:

 Dictionary<string, List<Car>> mydictionary;

I could store the whole thing with a string key as "MyDictionary" and then drill down once i pull out the object.

 HttpContext.Cache.Add("MyDictionary",  
   mydictionary, 
   null, 
   Cache.NoAbsoluteExpiration,
   new TimeSpan(10, 0, 0),
   CacheItemPriority.Normal,
   null);

 var myDict = HttpContext.Cache["MyDictionary"] as Dictionary<string, List<Car>>;

The other thing i could do is break it down and store each item in my dictionary separately in the cache (given the cache is a dictionary anyway).

 Dictionary<string, List<Car>> mydictionary;

 foreach (var item in mydictionary.Keys)
 {
      HttpContext.Cache.Add(item, mydictionary[item], null, Cache.NoAbsoluteExpiration, new TimeSpan(10, 0, 0), CacheItemPriority.Normal, null);
 }

 var myitem = "test";
 var myDict = HttpContext.Cache[myItem] as List<Car>;

Would the performance implication be very different (given i am assuming that everything is in memory anyway ?)

Adding an additional answer here as I feel the existing one capture the 'what' but not enough of the 'why'.

The reason it's best to store individual entries separately in the cache have little to do with perf. Instead, it has to do with allowing the system to perform proper memory management.

There is a lot of logic in the ASP.NET cache to figure out what to do when it runs into memory pressure. In the end, it needs to kick out some items, and it needs to do this in the least disruptive way possible. Which items it chooses to kick out depends a lot of whether they were accessed recently. There are other factors, like what flags are passed at caching time. e.g. you can make an item non-removable, and it'll never be kicked out.

But going back to the question, if you store your entire dictionary as a single item, you are only leaving two options to the ASP.NET memory manager: keep the entire thing alive, or kill the whole thing. i.e. you completely lose the benefit of having your 'hot' items stay in the cache, while your rarely accessed memory-hogging items get kicked out. In other words, you lose any level of caching granularity.

Of course, you could choose to implement your own scheme in your dictionary to remove items that are rarely used. But at that point you're re-inventing the wheel, and your new wheel will not work as well since it won't coordinate with the rest of the system.

Weird 404 error in ASP.NET MVC when including "con"

8 votes

I'm going through some of the crawl errors on an MVC application I maintain, and found a 404 error for a URL that looked like it should be valid.

The URL is of the format: /gifts/{categoryName}/{productName}/{productId}/

For some reason, when the productName is set to the value "con" I just get a 404 error. Any other value (different or same length of string) and it seems to work fine.

Has anyone ever seen anything like this before?

con is a reserved word and therefore cannot be put in an MVC route

You need to add the following to your web.config:

<configuration>
  <system.web>
    <httpRuntime relaxedUrlToFileSystemMapping="true"/>

    <!-- ... your other settings ... -->
  </system.web>
</configuration>

See this article for more information:

Putting the Con (COM1, LPT1, NUL, etc.) Back in your URLs

SocketException when calling WCF service from MVC on same server

8 votes

I have a Windows 2008 Server with IIS 7.5 and one IP. There are two Application under the root, /web and /service. /web is a MVC4 application, and /service is a WCF 4.0 service.

When I consume the service from MVC, I use the following code:

// Create the web request  
HttpWebRequest request = WebRequest.Create(TripServiceUrl + id) as HttpWebRequest;

// Get response  
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    // Get the response stream  
    StreamReader reader = new StreamReader(response.GetResponseStream());

    // Console application output  
    tripJson = reader.ReadToEnd();
} 

I get the following SocketException:

[SocketException (0x274c): A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 10.243.6.43:80]
System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress) +273
System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception) +584

However, I can see 10.243.6.43:80 (an internal address) from a browser on the server and successfully call the service. The IP is not publicly accessible.

What configuration should I have to do to make a self referential call like that work?

It's probably a loopback problem (security issue). See http://support.microsoft.com/kb/896861.

To summarize:

In Registry Editor, locate and then click the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa Right-click Lsa, point to New, and then click DWORD Value. Type DisableLoopbackCheck, and then press ENTER. Right-click DisableLoopbackCheck, and then click Modify. In the Value data box, type 1, and then click OK.

Don't follow the step about DisableStrictNameChecking.

You'll also find a lot of reasons not to do this (you are, after all, disabling a security check), followed by a lot of people saying it's the only way to get SharePoint to work properly. In any event, it will help you determine if this is the problem.

I want to understand the lambda expression in @Html.DisplayFor(modelItem => myModel.FirstName)

7 votes

I'm fairly new at C# and MVC and have used lambda's on certain occasions like as anonymous methods and on LINQ.

Usually I see lambda expressions in the form of

(x => x.Name), (x => { Console.WriteLine(x))

, and etc.

I understand that lambda = "goes to". I have never seen a lambda expression where the left parameter is not used.

I don't know how to translate this lambda expression though

@Html.DisplayFor(model => item.FirstName)

Can anyone shed a light for me on this one? Shouldn't this be

(modelItem => modelItem.FirstName)?

I got this from: http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/getting-started-with-mvc3-part5-cs

A lambda expression is a way to write an anonymous function, i.e. a function without a name. What you have on the left side of the "arrow" are the function parameters, and what you have on the right side are the function body. Thus, (x => x.Name) logically translates to something like string Function(Data x) { return x.Name } the types string and Data will obviously vary and be derived from the context.

The absence of the left-side parameter translates into a function without parameters, so that this (() => someVariable) logically translates to this: string Function() { return someVariable; }

At this point you might start wondering, where someVariable comes from, it's not a function parameter and it is not defined in the function. You would be correct, a function like this would never compile. However the lamda function like this is perfectly fine, as it allows outer-scope variables be lifted and used this way. (Internally a wrapper class is created where the variables that are used in the lambda expression become fields)

Now let's see what model => item.FirstName means. Logically it would translate to string Function(Model model) { return item.FirstName; }. Basically this is a function with a parameter, but this parameter is not used.

And now, the last bit of the information. Although lambda expressions represent functions in the end, sometimes they are created not with the purpose of actually being executed (although potentially they can). A lambda expression can be represented in form of an expression tree. This means that instead of executing it it can be parsed.

In this particular case MVC engine does not run the function that the lamba expression represents. Instead the expression is parsed so that MVC engine knows what html to emit for this particular line. If your data item does not come from your model object directly, the left part of the lambda expression does not matter.

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.

Concerned about deadlocks with C# StreamReader

5 votes

Just a general question, I'm developing an ASP.NET MVC 3 web application that reads from a configuration file using the Stream Reader inside a Using statement for automatic disposal as follows:

using (StreamReader sr = new StreamReader(filepath))
{

}

My concern is that when multiple users are running the application, a deadlock will occur when multiple instances of the application are reading values from the configuration file. My question is, are deadlocks an issue when working with the Stream Reader class? Intuitively I would think not, since I'm assuming the Stream Reader is opening the file in read-only mode and there are no external processes writing to the configuration file other than manual edits. I just wanted to be sure whether or not this would be an issue. Any insight is appreciated.

My concern is that when multiple users are running the application, a deadlock will occur when multiple instances of the application are reading values from the configuration file

No, don't worry. No deadlock will occur. You are opening the file for reading. So you could have concurrent readers. But if you write to this file in some other location of your code that you will get an exception. But no deadlock. If you want to properly synchronize readers and writers to some shared resource such as a file you could use the ReaderWriterLockSlim class. If you never write to the file (from the same process or some other process) then you are fine. But if you never write to the file, to avoid reading and parsing this file everytime, you should only read it once and cache it in some memory structure. For example that's how the .NET application configuration system works. It reads and parses the app/web.config once when running the application and then stores it into memory for faster access. But of course everything will depend on your exact scenario.

Change default ASP MVC Request Header to add your own values

5 votes

Im trying to change all my ASP MVC HTTP response headers to have another value by default for implementing Pingback auto-discovery in my blog application.

The default header (on Cassini) is :

Cache-Control   private
Connection  Close
Content-Length  20901
Content-Type    text/html; charset=utf-8
Date    Fri, 20 Apr 2012 22:46:11 GMT
Server  ASP.NET Development Server/10.0.0.0
X-AspNet-Version    4.0.30319
X-AspNetMvc-Version 3.0

and i want an extra value added :

X-Pingback: http://localhost:4912/pingback/xmlrpcserver

I have googled a bit and found a neet solution : -- to derive from ActionFilterAttribute and override the OnResultExecuted method:

public class HttpHeaderAttribute : ActionFilterAttribute
    {

        public string Name { get; set; }
        public string Value { get; set; }

        public HttpHeaderAttribute(string name, string value)
        {
            Name = name;
            Value = value;
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            filterContext.HttpContext.Request.Headers.Add(Name, Value);
            base.OnResultExecuted(filterContext);
        }

    }

And then simply i put the attribute on my Controllers methods:

[HttpHeader("X-Pingback","http://localhost:4912/pingback/xmlrpcserver")]
        public ActionResult Index()
        {
            var allArticles = _repository.GetPublishedArticles(SortOrder.desc);
            return View(allArticles);
        }

When i runt the app i get the following error : enter image description here

Any ideas?

This may or may not work (obviously if it doesn't I'll delete the answer for future users). It sounds like from the exception Operation is not supported by this platform, that Cassini many not support custom headers (which would be quite strange, but a possibility). What I would suggest is to make sure you are using Visual Studio 2010 SP1, then install IIS Express (which is an upgrade to Cassini and is much more like real IIS), and then switch your project to use IIS Express and see if you get the same exception.

Switching from Cassini to IIS Express

Additionally, you may want to review Why does HttpCacheability.Private suppress ETags? as it may also give you an alternative solution.

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.

Asp.net MVC Model for view and Layout

4 votes

I've been trying to find a good way to handle the Models of our Asp.net MVC websites when having common properties for all the pages. These properties are to be displayed in the Layout (Master Page). I'm using a "BaseModel" class that holds those properties and my Layout use this BaseModel as its model.

Every other model inherits from that BaseModel and each has specific properties relative to the view it represents. As you might have guessed, my Models are actually View Models even if that's not quite relevant here.

I have tried different ways to initialize the BaseModel values

  1. By "hand" in every view
  2. Having a base controller that has an Initialize virtual method to do it (so specific controller can implement specific common behavior for exemple)
  3. Having a base controlelr that override OnActionExecuting to call the Initialize method
  4. Using a helper class to do it outside of the controller
  5. Using a Model Factory

But none of those really appeal to me:

  1. Seems obvious to me, but DRY is one reason enough to justify that (actually I never tried that solution at all, I'm just putting it to be able to loop on that point in the last point).
  2. I don't like that one because it means that whenever a new Controller is added, you need to know that it has to inherit from the BaseController and that you need to call the Initialize method, not to mention that if your controller has overriden the base one, to call the base anyway to maintain the values.
  3. see next point
  4. and 3. are a variation on the same topic but that doesn't really help with the issues of the second solution.
  5. My favorite so far, but now I have to pass a few more variables to set those values. I like it for the inversion of dependence. But then if I want to provide values from the session, I need to pass them explicitly for exemple, then I'm back to square one as I have to provide them by hand (being references or through an interface of any kind)

Of course, (almost) all of those solutions work, but I'm looking for a better way to do it.

While typing this question, I found maybe a new path, the builder pattern that might also do, but implementations can become quickly a burden too, as we can have dozens of views and controllers.

I'll gladly take any serious recommandation/hint/advice/patterns/suggestion !

Update

Thanks to @EBarr I came up with another solution, using an ActionFilterAttribute (not production code, did it in 5 minutes):

public class ModelAttribute : ActionFilterAttribute
{
    public Type ModelType { get; private set; }

    public ModelAttribute(string typeName) : this(Type.GetType(typeName)) { }

    public ModelAttribute(Type modelType)
    {
        if(modelType == null) { throw new ArgumentNullException("modelType"); }

        ModelType = modelType;
        if (!typeof(BaseModel).IsAssignableFrom(ModelType))
        {
            throw new ArgumentException("model type should inherit BaseModel");
        }
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var model = ModelFactory.GetModel(ModelType);

        var foo = filterContext.RequestContext.HttpContext.Session["foo"] as Foo;

        model.Foo = foo;
        model.Bar = somevalue;

        filterContext.Controller.TempData["model"] = model;
    } 
}

Calling it is then really simple:

[Model(typeof(HomeModel))]
public ActionResult Index()
{
    var homeModel = TempData["model"] as HomeModel;

    // Add View Specific stuff

    return View(homeModel);
}

And it gives me the best of every world. The only drawback is to find a proper way to passe the model back to the action.

Here it's done using the TempData object, but I also consider updating the model that one can find in the ActionParameters.

I'm still taking any serious recommandation/hint/advice/patterns/suggestion for that, or the previous points.

The idea that gave me @EBarr to use an action filter was actually working but felt wrong in the end, because there was no clean way to retrieve the model without passing through a viewbag, or the httpcontext items, or something alike. Also, it made mandatory to decorate every action with its model. It also made the postback more difficult to handle. I still believe that this solution has merits and might be useful in some specific scenarios.

So I was back to square one and started looking more into that topic. I came to the following. First the problem has two aspects

  1. Initializing the data for the views
  2. Rendering the data

While looking for more idea, I realized that I was not looking at the problem from the right perspective. I was looking at it from a "Controller" POV, whereas the final client for the model is the view. I was also reminded that the Layout/Master page is not a view and should not have a model associated with it. That insight put me on what feels the right path for me. Because it meant that every "dynamic" part of the Layout should be handled outside of it. Of course, sections seems the perfect fit for that, because of their flexibility.

On the test solution I made, I had (only) 4 different sections, some mandatory, some not. The problem with sections, is that you need to add them on every page, which can quickly be a pain to update/modify. To solve that, I tried this:

public interface IViewModel
{
    KeyValuePair<string, PartialViewData>[] Sections { get; }
}

public class PartialViewData
{
    public string PartialViewName { get; set; }
    public object PartialViewModel { get; set; }
    public ViewDataDictionary ViewData { get; set; }
}   

For exemple, my model for the view is this:

public class HomeViewModel : IViewModel
{
    public Article[] Articles { get; set; }             // Article is just a dummy class 
    public string QuickContactMessage { get; set; }     // just here to try things

    public HomeViewModel() { Articles = new Article[0]; }

    private Dictionary<string, PartialViewData> _Sections = new Dictionary<string, PartialViewData>();
    public KeyValuePair<string, PartialViewData>[] Sections
    {
        get { return _Sections.ToArray(); }
        set { _Sections = value.ToDictionary(item => item.Key, item => item.Value); }
    }
}

This get initialized in the action:

public ActionResult Index()
{
    var hvm = ModelFactory.Get<HomeViewModel>(); // Does not much, basicaly a new HomeViewModel();

    hvm.Sections = LayoutHelper.GetCommonSections().ToArray(); // more on this just after
    hvm.Articles = ArticlesProvider.GetArticles(); // ArticlesProvider could support DI

    return View(hvm);
}

LayoutHelper is a property on the controller (which could be DI'ed if needed):

public class DefaultLayoutHelper
{
    private Controller Controller;
    public DefaultLayoutHelper(Controller controller) { Controller = controller; }

    public Dictionary<string, PartialViewData> GetCommonSections(QuickContactModel quickContactModel = null)
    {
        var sections = new Dictionary<string, PartialViewData>();
        // those calls were made in methods in the solution, I removed it to reduce the length of the answer
        sections.Add("header",
                     Controller.UserLoggedIn() // simple extension that check if there is a user logged in
                     ? new PartialViewData { PartialViewName = "HeaderLoggedIn", PartialViewModel = new HeaderLoggedInViewModel { Username = "Bishop" } } 
                     : new PartialViewData { PartialViewName = "HeaderNotLoggedIn", PartialViewModel = new HeaderLoggedOutViewModel() });
        sections.Add("quotes", new PartialViewData { PartialViewName = "Quotes" });
        sections.Add("quickcontact", new PartialViewData { PartialViewName = "QuickContactForm", PartialViewModel = model ?? new QuickContactModel() });
        return sections;
    }
}

And in the views (.cshtml):

@section       quotes { @{ Html.RenderPartial(Model.Sections.FirstOrDefault(s => s.Key == "quotes").Value); } }
@section        login { @{ Html.RenderPartial(Model.Sections.FirstOrDefault(s => s.Key == "header").Value); } }
@section       footer { @{ Html.RenderPartial(Model.Sections.FirstOrDefault(s => s.Key == "footer").Value); } }

The actual solution has more code, I tried to simplify to just get the idea here. It's still a bit raw and need polishing/error handling, but with that I can define in my action, what the sections will be, what model they will use and so on. It can be easily tested and setting up DI should not be an issue.

I still have to duplicate the @section lines in every view, which seems a bit painful (especialy because we can't put the sections in a partial view).

I'm looking into the templated razor delegates to see if that could not replace the sections.

Create common ActionResult

4 votes

I have the following in my controller;

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

    [HttpPost]
    public ActionResult cocktailLoungebarattendant(string name, string email, string phone)
    {
        return View();
    }

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

    [HttpPost]
    public ActionResult merchandisecoordinator(string name, string email, string phone)
    {
        return View();
    }

This only occurs 4 times but it bugs me that I have the code repeated 4 times.

I then have a BaseController that then grabs the parameters and does stuff with them;

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {

I'd like to be able to do away with the Post ActionResult's and have a single one in a base controller say.

Is this even possible?

What you could do is this: In your (base)controller add:

protected override void HandleUnknownAction(string actionName)
    {
        var controllerName = GetControllerName();
        var name = GetViewName(ControllerContext, string.Format("~/Views/{0}/{1}.cshtml",controllerName, actionName));
        if (name != null)
        {
            var result = new ViewResult
                            {
                                ViewName = name
                            };
            result.ExecuteResult(ControllerContext);
        }
        else
            base.HandleUnknownAction(actionName);
    }

    protected string GetViewName(ControllerContext context, params string[] names)
    {
        foreach (var name in names)
        {
            var result = ViewEngines.Engines.FindView(ControllerContext, name, null);
            if (result.View != null)
                return name;
        }
        return null;
    }

This will try to check if a view exists for methods not defined. I think you can extend it from here on your own to suit your needs.

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.

Entity Framework 4 (using EDMX), how to add a field into to model that DB does not have the field actually

4 votes

I need to add a field into model that Database does not have the field actually.

Because, firstly I tried to add the field into Entity class only.

public partial class Weborder
{
  (Auto Generated)
  public int orderno {get; set;}
  .
  .
  .
  (Add Manually)
  public string newField1 {get; set;} //this is new field that DB does not have
  public string newField2 {get; set;} //this is new field that DB does not have
}

and later, when I update EDXM then EDMX remove the new fields because the database does not have the field. :(

So I add the field into EDMX model manually. (Add -> Scalar Property)

then an error occur while compiling, the error message say :

Error   1   Error 3004: Problem in mapping fragments starting at line 399:No mapping specified for properties ...
An Entity with Key (PK) will not round-trip when:...

Anybody know how to add new fields into entity class ?

Thank you!

EDITED FOR : If your model is a representation of your database and in the database you don't have the field, why do you want to add it manually?

=>

When retrieve data, the return type of object is the entity class.

and before passing data from controller to view, I need to add more data(fields) into the IQueryable result.

ex)

public DbSet<WEBORDERLN> WEBORDERLNs { get; set; }

//repository
public IQueryable<WEBORDERLN> WebOrderLns
{
      get { return context.WEBORDERLNs; }
}

and now I get the weborderln data in controller. and before passing view, I need to

add extra data into the result.

var data = webOrderLnRepository.WebOrderLns.Where(e => e.PICKNO == OrderNo).ToList();

foreach (WEBORDERLN weborderln in data)
{
   weborderln.[NEW FIELD] = "EXTRA DATA";   //// FOR THIS, I NEED TO ADD NEW FILED INTO ENTITY CLASS
}

//return data

I hope it could explain the question :)

Thanks again.

You must create a new partial part of your entity class (in the new .cs file) and add new fields to that class. You must not modify the partial part created by autogeneration because autogenerated files will be overwritten every time you change EDMX file. You also must not include the field in EDMX because EDMX defines your mapping to database = it contains only fields in database.

Create a new file WebOrderPart.cs in the same assembly and namespace as your autogenerated classes containing:

public partial class Weborder
{
  public string newField1 {get; set;} 
  public string newField2 {get; set;} 
}

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();
    }