Passing arrays into a ASP.NET Web Api method as parameters

Here is an easy way to pass in a array of values as parameters in a ASP.NET Web Api method.

1
2
3
4
5
6
        [HttpGet()]
        public HttpResponseMessage FindByMembers([FromUri]Int32[] ids = null)
        {
           //Do stuff
            return Request.CreateResponseMessage(HttpStatusCode.OK);
        }

The Url will be http://mywebsite/api/mycontroller/findbymembers/?ids=1&ids=2&ids=3.

Happy API coding!

Unable to update the EntitySet because it has a DefiningQuery and no element exists in the element to support the current operation.

I came across this error Unable to update the EntitySet because it has a DefiningQuery and no element exists in the element to support the current operation.. This was because there was a change in the database but it wasn’t reflected in the EDMX file. The exact details was a relationship was deleted but the change wasn’t picked up in the Entity Framework which caused the error.

Installing Windows 8 on VM Player 4+

I got the following error when trying to install Windows 8 preview on VM Player.
The com­puter restarted unex­pect­edly or encoun­tered an unex­pected error. Win­dows instal­la­tion can­not pro­ceed. To install Win­dows, click ‘OK’ to restart the com­puter, and then restart the installation.

When installing on VMware Work­sta­tion 8:

  1. Use Typ­i­cal (Easy install)
  2. Point to .iso file, Dis­re­gard warn­ing about failed OS detec­tion.
  3. Choose Win­dows 7 x64 or Win­dows 7
  4. Type a login name. Ignore prod­uct key and pass­word.
  5. Name your vir­tual machine and choose a loca­tion.
  6. Set HDD as 20GB in 1 file.
  7. Cus­tomize hard­ware: Set mem­ory at 2 GB RAM. Keep 1 CPU/Core. Remove floppy drive and printer from HW con­fig­u­ra­tion.
  8. When the vir­tual machine starts boot­ing, click on the floppy drive icon, and choose dis­con­nect. Thus you won’t be using the autoinst.flp con­fig­u­ra­tion file, and the instal­la­tion will progress with­out a hitch.

Credits to this link

MySqlConnector working on Visual Studio 2011 Beta

I’m currently working on a project using the latest and greatest (perhaps not?) Visual Studio 2011 Beta with mysql. It’s quite a painful task at the moment as i’m using the Entity Framework as my ORM. However, for all of you who want to get the MySqlConnector working with Visual Studio 2011 Beta, then I suggest you visit this page. It’s in a different language so make sure you have your favorite language translator ready. It’s a good start, but it still doesn’t integrate into the Entity Framework section so you cannot generate models etc from mysql databases in VS 2011 Beta. At the moment I’m using the Code First approach with an existing mysql database and using the Fluent API to map the fields together, what a task!

http://social.technet.microsoft.com/wiki/pt-br/contents/articles/10476.instalando-mysql-connector-no-visual-studio-2011-beta.aspx

Unit Testing ObjectResult

I came across an interesting scenario where I wanted to unit test an imported function in the Entity Framework. The initial problem is that an imported function generates code like this:

1
2
3
4
5
public virtual ObjectResult<MyObject> GetData()
        {
   
            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<MyObject>("GetData");
        }

The key method here is the results are returned as the ObjectResult object which 1) cannot be mocked (using RhinoMocks) because it’s sealed. There are no constructors available to create concrete instances of the object. So the best solution I can come up with is to create a new interface and create two classes that implement the interface, one for the real application and one for unit testing. From here, the unit testing class which has the interface can return anything it likes i.e. fake objects while the other class can call the function import method and return the results.

Firstly, I create the interface

1
2
3
4
5
6
public partial interface IExtendedEntities
    {
       
        IEnumerable<MyObject> GetDataWrapper();

    }

Secondly, I create the class that will use this interface for the real application.

1
2
3
4
5
6
7
public partial class MyClassReal : DbContext, IExtendedEntities
    {
        public IEnumerable<MyObject> GetDataWrapper()
        {
            return this.GetData().AsEnumerable();
        }
    }

Thirdly, create the class that uses the interface for unit testing

1
2
3
4
5
6
7
public partial class MyClassFake : DbContext, IExtendedEntities
    {
        public IEnumerable<MyObject> GetDataWrapper()
        {
            return Builder<MyObject>.CreateListOfSize(10).Build();
        }
    }

When I’m implementing the logic, I can inject (using nInject) an object of the interface IExtendedEntities and call GetDataWrapper();

When unit testing, I can create a new MyClassFake object and return a list of test data. This gives me the control to create a test case of specific test data to be put through the method that gets called to return a set of results from the Imported Function.

Tracking and Not Tracking Objects returned from SqlQuery in Entity Framework

If you don’t want objects to be tracked by the context, you can do this:

1
2
3
4
public ObjectResult<MyObject> GetData()
{
         return this.Database.SqlQuery<MyObject>("call GetData(@p0,@p1,@p2,@p3)", 1, 2, 3, 4);
}

If you want to track objects by the context, you can do this:

1
2
3
4
public ObjectResult<MyObject> GetData()
{
     return ((DbSet<MyObject>)this.MyObjects).SqlQuery("call GetData (@p0,@p1,@p2,@p3)", 1, 2, 3, 4);
}

The different is when you call SqlQuery from the objects DbSet, this will automatically track objects with the current database context.

Referenced Projects in a solution disappear on compile time Visual Studio 2010

Take the following example of a solution:

  • MyProject
  • MyProject.Core
  • MyProject.Infrasturcture

I decide to add a new console application called MyProject.Console. I reference the MyProject.Core into this console application. Everything is working fine until I try to build and run the console application. I get a error saying “Could not find the referenced Assembly.”.

I figured out that when I created the new console application in Visual Studio 2010 it defaulted to .NET 4 Client Profile as the framework and not .NET 4. This is because all my other projects were using the .NET 4 framework.

References

http://stackoverflow.com/questions/4286599/referenced-project-gets-lost-at-compile-time

The property could not be set to a ‘Int16′ value. You must set this property to a non-null value of type ‘Int32′.

I came across the following error when trying to map a stored procedure to a complex type in EF 4+.

The property could not be set to a ‘Int16′ value. You must set this property to a non-null value of type ‘Int32′.

The problem was the Entity Framework was thinking the return data type was Int16 but in fact the complex type value was specified as Int32.

The solution was to make sure that your results from the stored procedure are explicitly set and cast to the right data types. You can do this by using the convert function in T-SQL. Example below.

1
 select convert(int,myValue) from foo

Once you do implement this function into your stored procedures, you can update your mappings in EF and the problem will be fixed (well for me anyway).

Giving Enum’s descriptions

Enums are very good for giving descriptions to values especially numeric values. By default though a enum value name cannot have spaces. Look at the following which shows an example of no spaces between the first enum value name.

1
2
3
4
enum myEnum
{
   Icannothaveaspace = 1
}

A good way to solve this problem is to use the Description attribute from the System.ComponentModel namespace. We can use this attribute to give each enum value a descriptive meaning.

1
2
3
4
5
6
7
8
9
using System.ComponentModel;

 public enum MyEnum
    {
        [Description("Authorised Contact")]
        AuthorisedContact = 1,
        [Description("Assigned Contact")]
        CoauthorisedContact = 2
    }

From here we can create a extension method that uses reflection to get the description attribute for the selected enum value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static class Extensions
    {
        /// <summary>
        /// Get the description of a enum value using the description attribute
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetEnumDescription(this Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());

            DescriptionAttribute[] attributes =
                (DescriptionAttribute[])fi.GetCustomAttributes(
                typeof(DescriptionAttribute),
                false);

            if (attributes != null && attributes.Length > 0)
                return attributes[0].Description;
           
            return value.ToString();
        }
    }

To use this, just call GetEnumDescription to get the description of a enum value.

1
2
3
4
5
6
7
8
9
  using Extensions; //Make sure that you use this to get the extension method
 
  public myClass
  {
      public void foo()
      {
          var myDescription = MyEnumValue.GetEnumDescription();
      }
  }

Setting the screen position when visiting previous page with jQuery

The scenario

This problem came while I was working on a client’s website. Take this scenario. I have a listing page (similar to a listing page from www.trademe.co.nz or www.ascent.co.nz ). They have a lot of listings. Each listing has a hyperlink going to a detail page which describes more about each listing.
If you have quite a large page of listings, the user has to scroll down the page to find the listing they want to click on. The problem is, when they click on the link and go to the details page, what happens when the click back and they end up back at the top of the page again? This can be quite annoying. It would be “nice” to get the browser to go back to the previous position on the listing page.

The Approach

We achieve this but attach a click event handler to the specific a tags that we want to record the last clicked position from the user before we redirect to the next page. This means when the user goes back to the previous page they will be taken to the exact position on the page. When the click event happens we always override what was in the cookie so that we don’t end up with several pages and positions. We don’t want a user to go to another page they have been to before and set the scroll position, it should only happen to the previous page.

Here is the code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
var COOKIE_NAME = "scroll";
 
$(document).ready(function () {
    // Check to see if the user already has the cookie set to scroll
    var scrollPosition = getCookiePosition(COOKIE_NAME);
    if (scrollPosition.length > 0) {
        // Scroll to the position of the last link clicked
        window.scrollTo(0, parseInt(scrollPosition, 10));
    }
 
    // Attach an overriding click event for each link
    // saveScrollPosition function can be called before the user is redirected.
    $("a.savel").each(function () {
        $(this).click(function () {
            saveScrollPosition($(this));
        });
    });
});
 
// Get the offset (height from top of page and the current page url) of the link element
// and save it in a cookie.
function saveScrollPosition(link) {
    var linkTop = link.offset().top;
    setCookie(COOKIE_NAME, "pos=" + linkTop + "&link=" + escape(window.location.pathname), 1);
}
 
//Trim whitespaces
function trim(str) {
   return str.replace(/^\s+|\s+$/g, '');
}
// Get cookie helper function
function getCookiePosition(name) {
    if (document.cookie.length > 0) {
        //Get the right cookie
        var cookies = document.cookie.split(";");
        for (var i = 0; i < cookies.length; i++) {
           
            if (trim(cookies[i].split("=")[0]) == COOKIE_NAME) {
                //Get the position of the & sign
                var pos = cookies[i].indexOf("&");
                if (pos > -1) {
                    //Get value
                    var scrollValue = cookies[i].split("=")[2].substring(0, cookies[i].split("=")[2].indexOf("&"));
                    var link = unescape(trim(cookies[i].split("=")[3]));
                    //if the link is the same as the current page, then assume user wants to go back to the same position
                    if (link == window.location.pathname) return scrollValue;
                }
                return "";
            }
        }
        return "";
    }
    return "";
}
 
//Method to create a new cookie
function createCookie(name, value, days) {
    if (days) {
        var date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        var expires = "; expires=" + date.toGMTString();
    }
    else var expires = "";
    document.cookie = name + "=" + value + expires + "; path=/";
}
 
// Set cookie
function setCookie(name, value, expiredays) {
    //Remove all other cookies
    var cookies = document.cookie.split(";");
    for (var i = 0; i < cookies.length; i++) {
        if (trim(cookies[i].split("=")[0]) == COOKIE_NAME) {
            createCookie(trim(cookies[i].split("=")[0]), "", -1);
        }
    }
    //Set the new cookie
    createCookie(name, value, expiredays);
}