Monday 12 December 2011

How to force view compilation in an ASP.NET MVC project

When you build an ASP.NET MVC project, the default behaviour is to exclude view files from compilation. To include views unload the project (in Solution Explorer right click the project and select Unload Project) and edit the project file (right click the project node and select Edit <project name>.csproj).  Locate the MvcBuildViews setting and change this to true.  On reloading the project, building will now compile all views.

Note that this will include all view files in the project's Views folder on disk, even if these are not added to the project.

Tuesday 4 October 2011

Using the ASP.NET membership provider in an MVC controller

You can refer to the default ASP.NET membership provider in the controller action using the Membership.Provider object, just as in ASP.NET Web Forms. This is because ASP.NET MVC uses the same ASP.NET infrastructure as Web Forms. This is how the default AccountController, built when you select the ASP.NET MVC 3 Internet Application template, provides authentication functionality. It declares an IMembershipService interface dependency, to abstract the authentication functionality, and instantiates this with the AccountMembershipService concrete class in the controller’s Initialize method:

public IMembershipService MembershipService { get; set; }
protected override void Initialize(RequestContext requestContext)
{
    if (FormsService == null) { FormsService = new
    FormsAuthenticationService(); }
    if (MembershipService == null) { MembershipService = new
    AccountMembershipService(); }

    base.Initialize(requestContext);
}


The IMembershipService interface and AccountMembershipService implementation are in the AccountModels file.

Of course you can check whether the current identity is authorized without having to directly use the Membership.Provider object, by using the AuthorizeAttribute attribute.

[Authorize]
public ActionResult About()
{
    return View();
}


Adding this attribute to the action method declaration will make the MVC runtime check whether the identity is authenticated. If the identity is not authenticated, the runtime will throw a SecurityException exception.

Thursday 29 September 2011

C# arithmetic operators

Because I have a terrible memory…

Operation Operator Remarks 
Add+Redefined on strings to provide string concatenation, so no other separate string concatenation operator is required corresponding to VB’s & operator.
Increment++The ++x form is a prefix operation. The result of the operation is the value of the operand after it has been incremented.
The x++ form is a postfix operation. The result of the operation is the value of the operand before it has been incremented.
Decrement--The --x form is a prefix operation. The result of the operation is the value of the operand after it has been decremented.
The x-- form is a postfix operation. The result of the operation is the value of the operand before it has been decremented.
Division/Redefined for each type – i.e. there is no separate integer division operator.
Modulus%

A full list of C# operators is in MSDN.

Friday 16 September 2011

The next release of .NET

A while ago some concerns were expressed regarding Microsoft’s plans for .NET, based on an article that was written in response to a Windows 8 preview in May (see earlier post). During the preview session, not much was mentioned about these plans.

In last week’s Windows 8 Build event, MS provided details on the forthcoming release of .NET 4.5. The following session outlines the new features in .NET 4.5 supporting Windows 8.

http://channel9.msdn.com/Events/BUILD/BUILD2011/TOOL-834T

Essentially this is a mainly incremental release (although including some substantial changes to the CLR to support new Windows 8 technologies). There is no evidence or suggestion that there are any plans to replace .NET with any framework based on HTML 5 and/or Javascript as suggested elsewhere.

Wednesday 14 September 2011

How to generate an entity from a stored procedure using EF

If you want to generate an entity from a stored procedure, you can do this using Entity Framework. Here’s how.

Add a new ADO.NET Entity Data Model item and generate the entity model from the required database as usual. In the Choose Your Database Objects step of the Entity Data Model Wizard, select the required stored procedures and click Finish.


Next, double click the generated .edmx node in Solution Explorer to open the EF designer, right click the designer surface and select Model Browser. In the Model Browser tab that appears, under the XXXModel.Store node (under the top .edmx node), right click the stored procedure and select the option Add Function Import. This will bring up the following dialogue.


To generate an entity that will contain all the columns returned from the stored procedure, click Get Column Information (which retrieves the schema from the stored procedure), then click Create New Complex Type to generate a type that returns all columns, or Entities to map the results to an existing entity. You can rename the type if required.


Now we can use this. If using Web Forms, we can set a grid view’s datasource using the method generated for the entity:

protected void Page_Load(object sender, EventArgs e)
{
   if (!Page.IsPostBack)
   {
      using (var myEntity = new Entities())
      {
         GridView1.DataSource = myEntity.procSupplierDepotList();
         GridView1.DataBind();
      }
   }
}


If the stored procedure takes input parameters, the generated method will expect corresponding arguments.

GridView1.DataSource = myEntity.procSupplierDepotList(id);

This will automatically generate the grid view columns from the data fields returned by the generated method. To display a subset of the fields, you can either set AutoGenerateColumns to false and specify the columns, e.g.

<asp:GridView ID="GridView1" runat="server” AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="Name"><ItemTemplate><asp:Literal runat="server" Text='<%# Eval("SupplierName") %>' /></ItemTemplate></asp:TemplateField>
<asp:TemplateField HeaderText="Code"><ItemTemplate><asp:Literal runat="server" Text='<%# Eval("SupplierCode") %>' /></ItemTemplate></asp:TemplateField>
</Columns>
</asp:GridView>


Alternatively, you can create an entity in the entity model that contains just the fields you want to display and set the generated method to return a collection of this entity. Note that you can modify the return value by double clicking the method in the Function Imports node.

Tuesday 13 September 2011

Getting AjaxLink to work in MVC 3

In a master/detail scenario, I had a view listing master items with a details link for each item. I wanted the details link to display child details using AJAX.

To do this you need the Ajax.ActionLink helper method. This takes (among other overloads) the following form:

@Ajax.ActionLink("Details", "Details", new { id = item.Id }, new AjaxOptions { UpdateTargetId = "divDetails" })

Here we are specifying the link text, the controller action, the route value and the target HTML element to update with the result of the Ajax request.

The Details action should return a PartialResult.

I had trouble getting this to work, as the Details action just posted back to a new page instead of the target element. Eventually I discovered that the key to getting this working is to add the following script (in _Layout.cshtml):

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

Friday 9 September 2011

Exception thrown the first time an NUnit test that opens a SQL connection is run

When running an NUnit test that opens a SQL connection, the first time the test is run you may get an error similar to the following:

System.Data.SqlClient.SqlException : A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - The pipe is being closed.)

Running the test again then passes.

This can happen in this scenario: NUnit has run data access code, creating a connection, then SQL Server is restarted. If this is the case, the cause of the exception is as follows. If SQL Server is restarted after ADO.NET has built a connection using the same connection string as that used by the failing test, ADO.NET will attempt to reuse that connection from the connection pool without checking whether the connection is invalid. Because SQL Server has been restarted the connection is no longer valid and the exception is thrown.

To demonstrate this, restart SQL Server, then run the test. The test will fail. If the test is run again, it will pass. Next, close NUnit, then restart SQL Server and reopen NUnit (in either order) and rerun the test. The test will pass.

Friday 12 August 2011

Manage Nuget Packages error

I suddenly started getting a weird error when trying to open the Nuget package manager (by right clicking the project in VS Solution Explorer and selecting the Manage Nuget Packages option). A dialogue appears containing the following error message and stack trace:

The composition produced a single composition error, with 2 root causes. The root causes are provided below. Review the CompositionException.Errors property for more detailed information.

1) Not implemented (Exception from HRESULT: 0x80004001 (E_NOTIMPL))

Resulting in: An exception occurred while trying to create an instance of type 'NuGet.VisualStudio.SolutionManager'.



It turns out this is a known problem if your solution contains an Installshield LE Setup project.

http://docs.nuget.org/docs/reference/known-issues

The workaround is to temporarily unload all Installshield LE setup projects in the solution. The Nuget package manager should now open correctly. Alternatively, if you close the solution, open a solution that does not contain any Installshield LE setup projects, open the Nuget package manager, then go back to the original solution, Nuget will open fine without unloading the setup projects.

Tuesday 12 July 2011

WCF CommunicationException TCP error

When trying to get a WCF service working over TCP, if the following CommunicationException is thrown on calling the ServiceHost object’s Open method:

A TCP error (10013: An attempt was made to access a socket in a way forbidden by its access permissions) occurred while listening on IP Endpoint=0.0.0.0:8080.

The likely causes are (1) the endpoint is being used by another running process or (2) a firewall is blocking access to this port.

To resolve this, run the following netstat command to see all sockets in use:

netstat –a

If this endpoint is listed in the output from netstat, try changing the service endpoint address to use a different port. (If the service is running on a computer with Windows Firewall, the Windows Security Alert dialogue may appear - the dialogue provides an option to allow access through the firewall.)

If the error is still being thrown, check that the port is not being blocked by a firewall.

Tuesday 5 July 2011

How to make NHibernate ignore rows with an incorrect discriminator for an association subclass

If you are mapping a class hierarchy to a single table in NHibernate by using a discriminator column to differentiate between the subclasses, if one of the concrete subclasses is being used as an association for another type you might run into the situation where incorrect data (i.e. discriminator value) in the database causes NHibernate to throw an exception complaining that it cannot find the class. (This can also happen if you are using the where attribute to exclude a reserved entity from being picked up.) The default behaviour is to throw an NHibernate.ObjectNotFoundException exception on accessing a row that cannot be mapped to the expected entity. Alternatively you can tell NHibernate to ignore this situation and substitute a null value for the missing association.
You do this by setting the not-found attribute of the many-to-one element to "ignore”. For example:

<many-to-one class="Engineer" column="EngineerID" name="Engineer" not-found="ignore"></many-to-one>

Monday 27 June 2011

The end of .NET is in sight?

Since the first week of June there have been a number of internet posts claiming that Microsoft are planning to dump the .NET platform in a bid to be seen as pursuing a platform independent strategy. For example:

http://www.i-programmer.info/professional-programmer/i-programmer/2591-dumping-net-microsofts-madness.html

This article provides a more balanced look at the story:

http://arstechnica.com/microsoft/news/2011/06/windows-8-for-software-developers-the-longhorn-dream-reborn.ars

The Microsoft Windows division have recently announced that they are providing HTML5 and Javascript APIs in Windows 8, and haven’t mentioned any planned new .NET features. As a result, some .NET developers have been demanding to know what Microsoft plans are for .NET. The Microsoft response has been, wait and see – we’ll explain all at the Build event in September. As a result theres a lot of hysteria about .NET being flushed down the toilet.

This announcement has basically been about the UI on Windows clients. The VS team has been working on better HTML5/Javascript support since VS 2010 came out last year. So Microsoft have decided the future of the UI involves HTML5/Javascript. So does virtually every other vendor. I wouldn’t be surprised if they do deprecate WPF and/or Silverlight and replace these with a new Windows client presentation technology, as there has been a disappointing takeup of these technologies.

I think that it is highly unlikely that Microsoft are going to expect developers to write middle tier components in Javascript, or any other dynamically typed language that lacks the safety of a static type system. I have not seen any mention of any plans to replace the CLR with new middleware. So I think it likely that the .NET platform will continue to be used for application services. There is a lot of .NET middleware functionality like WCF that is also going to have to be replaced if they retire the whole platform.

As far as the UI on web applications goes, again they have been providing better support for HTML5/Javascript, and have integrated support for the open source jQuery framework. The VS team are working on improving client side HTML5/Javascript debugging tools. They are still going to provide a web application framework to support HTML5/Javascript application development. If they keep the .NET platform, then I think it likely they will continue to develop ASP.NET to support HTML5 features.

This story is more about mismanaged communications with the developer community than anything else.

It should also be noted that much of the hype behind this story is coming from open source protagonists. It should also be pointed out that periodically Java gets a kicking in response to a bungled Oracle management initiative. For example:

http://www.devx.com/Java/Article/45527

http://www.readwriteweb.com/enterprise/2011/01/why-the-future-of-java-is-with.php

Before coming to any firm conclusions about the death of .NET I suggest we wait and see what Microsoft announces in September.

Friday 29 April 2011

Lack of NHibernate HQL support for question mark character in column name

If you’re faced with a database that contains reserved characters in some of its column names, NHibernate allows you to escape a column name in the mapping file by wrapping the column name in backticks, for example:

<class name="Foo">
   <property name="Bar" column="`Bar?`" />
</class>


This convention is used by NHibernate to generate SQL with the column name wrapped appropriately (e.g. [] for SQL Server). This works as intended for ICriteria queries and for HQL queries returning tuples in the following form:

session.CreateQuery("select Bar from Foo").List();

For SQL Server this results in the following SQL:

select foo0_.[Bar?] as col_0_0_
from Foo foo0_


The problem occurs if you use the entity selection form of the HQL query in conjunction with the generic List method:

session.CreateQuery("select foo from Foo foo").List<Foo>();

In this scenario, when constructing the SQL statement NHibernate interprets the question mark as a position parameter placeholder and substitutes the question mark with the parameter, i.e. the query winds up containing this column

foo0_.[Bar@p0]

instead of

foo0_.[Bar?]

Unfortunately this is a fault in NHibernate 3.1:

http://stackoverflow.com/questions/5805617/escaping-a-question-mark-character-in-a-column-name-in-nhibernate

Wednesday 9 March 2011

Deploying an MVC .NET 4 application on IIS 7.5

I recently incorporated MVC 3 into an existing web application project.  In the process I upgraded the target framework to .NET 4.0.  I faced a number of issues on deploying the application to IIS 7.5.

The first problem was an Internal Server Error 500 HTTP response from the server.  The solution to this is to check the web.config file and remove the system.web/httpModules and system.web/httpHandlers sections.  For my application these were redundant and I was able to simply remove them.  If any modules and/or handlers are still needed by the application these should be moved to system.webServer/modules and system.webServer/handlers respectively.

The next error I faced was a Internal Server Error 500.21 mysteriously complaining that Handler PageHandlerFactory-Integrated has a bad module ManagedPipelineHandler in its module list.  It seems this was caused by ASP.NET 4 not being correctly registered with IIS 7.5.  The solution is to check that the version of .NET installed on the computer running IIS matches the version targeted by the application (on my computer this is v4.0.30319), and run the aspnet_regiis tool for the correct .NET version, e.g.:

%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -i

You'll need to run this as an administrator.  You also need to check in IIS that the application pool used by the app is set to .NET 4.0 and Integrated managed pipeline.

If you're accessing a database and you haven't configured impersonation, you may need to set up a login for the ASP.NET identity. In ASP.NET 4 by default the application pool runs under the Windows account APPPOOL\[application pool name].  If you're using the default settings this will be APPPOOL\DefaultAppPool.  If you've upgraded to .NET 4, you'll have to create a login for each database your application accesses for the application pool Windows account.  (Alternatively if you have an existing login set up for the IIS 7 or 7.5 account you can change the application pool identity to this account.)

Having done these tasks I was able to run the application and log in, but as soon as I tried to access any MVC controller the server complained with a 404 response error.  After much googling I found this was fixed by applying hotfix KB980368.

This should now get you into the controller action.

One final error may crop up if you are restarting Cassini or IIS while testing the above, and this is related to any use of the Html.AntiForgeryToken method in views.  The default configuration is for a machine key to automatically generated: this will be invalidated each time IIS is restarted.  This is not a bug in the application: this is how it is supposed to work in production.  To clear this error you will need to clear out your application's cookies from your browser.  If you want to avoid this while testing - or in production if the ASP.NET process is being recycled (e.g. IIS restarts or if your application is being hosted in a web farm scenario) - you can hardwire a machine key by inserting a machine key section and either using a machine key generator tool to generate the machine key section e.g. aspnetresources.com/tools/machineKey or by manually creating a machine key section in system.web.

Tuesday 15 February 2011

How to display a jQuery datepicker control in an ASP.NET MVC partial view

When trying to use the jQuery datepicker in an ASP.NET MVC partial view I found that the calendar didn't display correctly.  On investigating the problen I realized I was calling the datepicker function in the wrong place.  Calling it in the partial view doesn't work - the MVC framework ignores the script when it renders the partial view in the .aspx view.  Calling it in the .aspx view's document ready event doesn't work either because at this stage it doesn't know about the control.

Here's a way to get it working.

Firstly, link the jQuery UI CSS file in the head section of the master file:

<link type="text/css" href="../../Content/jquery-ui-1.8.9.custom.css" rel="stylesheet" />

Add the jQuery script references to the head section of the master file (or in the appropriate asp:Content section in the .aspx view in which you're posting the partial view):

<script type="text/javascript" src="../../Scripts/jquery-1.4.1.js"></script>
<script type="text/javascript" src="../../Scripts/jquery-ui-1.8.9.custom.min.js"></script>

Create a Javascript function that calls the datepicker function:

<script type="text/javascript">
    function showDatePicker() {
        $('#date').datepicker();
    }
</script>

Declare the input element in the partial view, making sure to give it the same id you used in the call to datepicker:

<input type="text" name="date" id="date" />

Finally (this is the crucial bit), you need to call this function in the OnSuccess parameter of the Ajax call in the .aspx view, e.g.:

<li><%= Ajax.ActionLink("Some text to click on", "action_name", new { Id = Model.Id }, new AjaxOptions { OnSuccess = "showDatePicker", UpdateTargetId = "div_name" })%></li>

Note that this doesn't work if you use the OnComplete parameter.

Friday 7 January 2011

How to use a CTE to create a crosstab query

You can use a CTE with the ROW_NUMBER function to create a crosstab query. For example, say your data structure stores various types of event in a single table, but you need to report the various event dates in separate columns for each type of event. Here is how you might do this using a CTE joining on the output produced by ROW_NUMBER:

WITH eventTypeX AS
(
SELECT e.EventDate, e.JobID,
ROW_NUMBER() OVER(PARTITION BY e.JobID ORDER BY e.EventDate ASC) AS rn
FROM dbo.tblEvents
WHERE...
),
eventTypeY AS
(
SELECT e.EventDate, e.JobID,
ROW_NUMBER() OVER(PARTITION BY e.JobID ORDER BY e.EventDate ASC) AS rn
FROM dbo.tblEvents
WHERE...
)
SELECT j.JobID, j.JobDescription, e1x.EventDate AS FirstEventTypeX,
e2x.EventDate AS SecondEventType1, e1y.EventDate AS FirstEventTypeY,
e2y.EventDate AS SecondEventTypeY
FROM tblJobs j
LEFT OUTER JOIN eventTypeX e1x ON j.JobID = e1x.JobID AND e1x.rn = 1
LEFT OUTER JOIN eventTypeX e2x ON j.JobID = e2x.JobID AND e2x.rn = 2
LEFT OUTER JOIN eventTypeY e1y ON j.JobID = e1y.JobID AND e1y.rn = 1
LEFT OUTER JOIN eventTypeY e2y ON j.JobID = e2y.JobID AND e2y.rn = 2