2013-02-20

ASP.NET: Transform Web.config with Debug/Release on Build

Web.config Transformation

Did you ever wish you could run your web application with the Web.config being transformed according to the current Solution Configuration for Debug or Release directly from Visual Studio? Well, with some pre-build-magic we can do this.

Files in project

Create a file named Web.Base.config, besides the existing Web.Debug.config and Web.Release.config. This file will be the equivalent to your old Web.config, as it will be the base for the tranformation. You will end up with these files:

  • Web.config
  • Web.Base.config
  • Web.Debug.config
  • Web.Release.config

Web.config

Add the following configuration to the bottom of your .csproj-file, just before the closing </Project>-tag:

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets" />
<Target Name="BeforeBuild">
    <TransformXml Source="Web.Base.config" Transform="Web.$(Configuration).config" Destination="Web.config" />
</Target>

UPDATE: From a reminder in the comments I realized that I also have a problem with Visual Studio transforming the XML twice, when Publishing a project. The solution to this is to add a Condition to the Target-tag like this:

<Target Name="BeforeBuild" Condition="'$(PublishProfileName)' == '' And '$(WebPublishProfileFile)' == ''">

You can now build, run your project or publish it all depending on what Solution Configuration you have selected. Debug or Release. Just press your CTRL+SHIFT+B and see the Web.config-file be transformed.

Version control

I recommend that you leave Web.config out of your Version Control. This solution for transforming the Web.config on the fly would mean that this specific file would constantly be modified and if one person is working with Debug and another person is working with Release the Web.config would probably get big changes constantly.

Testing-tool

The people over at elmah.io has created the Web.config Transformation Tester, where you can try out what the result will be of combining a Web.config-file with a transformation.

The tool can even show you what the diff from the original file is when the transformation is applied.

2013-01-23

MVC: Get Current Action and Controller in View

Have you ever needed to know what Action and/or Controller that is currently used in your View? This might be most helpful in an Layout-file, used by another View.

string currentAction =
    ViewContext.Controller.ValueProvider.GetValue("action").RawValue.ToString();
string currentController =
    ViewContext.Controller.ValueProvider.GetValue("controller").RawValue).ToString();

Then you can do customization code like this in your _Layout.cshtml-file.

bool isIndexPage = currentAction.Equals("index", StringComparison.InvariantCultureIgnoreCase)
    && currentController.Equals("blog", StringComparison.InvariantCultureIgnoreCase);

Disclaimer: Of course this breaks the fundamental rules of separation of concerns in MVC, between the View and the Controller, but sometimes you just don't want, or can, pass around sufficient data between the View and the Controller.

2013-01-16

Create Human-Readable File Size Strings in C#

After needing functionality in C# for getting a human-readable file-size string I posted a question about it on Stackoverflow, as one does.

The accepted answer had about 72 lines of code. One explanation for this could be that I did specify that I wanted the solution to implement IFormatProvider. Not sure why I did that, probably seemed right at the time, in the end of 2008.

One creative solution was to use a Win32 API call to StrFormatByteSizeA

[DllImport("Shlwapi.dll", CharSet = CharSet.Auto)]
    public static extern long StrFormatByteSize(long fileSize, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder buffer, int bufferSize);

Compact, clean, cross-platform solution

For the sake of simplicity, readability and the bonus of cross-platform I re-implemented an earlier solution I found, that was written in JavaScript. But the solution was easily translateble into C#.

public static class FileSizeHelper
{
    private static readonly string[] Units = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

    private static string GetReadableFileSize(long size) // Size in bytes
    {
        int unitIndex = 0;
        while (size >= 1024)
        {
            size /= 1024;
            ++unitIndex;
        }

        string unit = Units[unitIndex];
        return string.Format("{0:0.#} {1}", size, unit);
    }
}

2013-01-10

FTP Upload File Using Only .NET Framework

Here an example of how to upload a file to a FTP-server, using the class FtpWebRequest, which is included in the .NET Framework.

string ftpPath = string.Format("ftp://{0}/{1}", urlOrIpNumber, filePath);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpPath);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential (userName, password);

byte[] fileContents = GetFileContent();
request.ContentLength = fileContents.Length;

using(var requestStream = request.GetRequestStream())
{
    requestStream.Write(fileContents, 0, fileContents.Length);
    requestStream.Close();
}

All you need to do is reference the System.Net namespace.

Update: Shorter code version

This code comes from Mads Kristensen, written in the middle of 2006.

private static void Upload(string ftpServer, string userName, string password, string filename)
{
   using (var client = new WebClient())
   {
      client.Credentials = new NetworkCredential(userName, password);
      client.UploadFile(ftpServer + "/" + new FileInfo(filename).Name, "STOR", filename);
   }
}

I'm not sure if there are any scenarios that this code doesn't work with.

2012-08-30

Squishify - Minify JavaScript & CSS Online

Squishify Screenshot

Squishify was created out of the need of a minifier for JavaScript. I quickly put together a web-app on AppHarbor to make minification always available quickly. The code is hosted on GitHub.

The application is an ASP.NET MVC-app, using Justin Etheredge's framework for minification called SquishIt. The app also uses ASP.NET Web API together with some simple jQuery to display the results of the minifications without any page-reloads.

The SquishIt-framework is a very easy to use and provides multiple minifiers for both JavaScript and CSS.

JavaScript minifiers:

* At the moment of writing this post, Google Closure is not working as expected, but should hopefully work soon.

CSS minifiers:

Enjoy it at squishify.apphb.com and fork it on GitHub.

2012-05-21

ASP.NET MVC 4 Razor v2 - New Features

Reference

With the imminent release of ASP.NET MVC 4 my previous post ASP.NET MVC 3 Razor - The Ultimate Quick Reference needed a follow-up on what's new in the view-engine Razor v2, that comes with MVC 4.

App-relative URLs automatically resolved

In Razor v1 your views would be littered with code like this:

<script src="@Url.Content("~/content/scripts.js")"></script>

But in Razor v2 you can shorten it with a tilde in front of the URL, which was used a lot in WebForms:

<script src="~/content/scripts.js"></script>

This will work for any HTML-attribute that starts with the title-sign.

Conditional attributes hides null-valued attributes

Razor v1 treated null-valued attributes as empty string, writing out attributes empty values. Razor v2 will instead skip even writing out the attribute that has a null value:

@{
    string itemId = string.Empty;
    string itemClass = "class-of-item";
    string itemValue = null;
}
<div id="@itemId" class="@itemClass @itemValue" rel="@itemValue"></div>

Will result in this HTML:

<div id="" class="class-of-item"></div>

Note that string.Empty still makes Razor v2 to write out the attribute. Any data-attribute will ignore this rule and always write out the attribute.

Support for unclosed HTML-tags

The HTML5-specs clearly states that unclosed HTML-tags are supported, but Razor v1 didn't have an advanced enough parser to support this. Razor v2 now supports this with the elements listed in W3C's spec.

What else?

There has been some major improvements on how the syntax-trees are structured and other deep functionality in the language. The focus was internal clean-up and future-proofing.

2012-05-14

DevSum Scheduler - Plan Your Attendance

DevSum 2012

Since I'm attending DevSum 2012 at the end of this month, I felt I needed to keep track of which talks to attend... but also the need to play around with some web-technologies.

From those needs I took some evening hours to build DevSum Scheduler. It's a web-app that allows you to highlight which talks you're going to attend.

The app uses HTML Agility Pack to get the data from DevSum's own website and then ASP.NET MVC Razor to display the content properly. To store this I've used HTML 5 LocalStorage to persist the choices made.

There are many other technologies used, which are listed on the about-page. Since the website is suppose to help the attendees by being available on their smart-phones, I've used CSS Media Queries for mobile layout and Modernizr for feature-detection in the web-browser.

Check out the full source-code on GitHub. Again, the outstanding AppHarbour has been used to quickly get the app on the Internet (through a GitHub-service hook of course).

2012-04-18

Making MVC 3 Razor IntelliSense work after installing MVC 4 Beta

After installing the MVC 4 Beta the IntelliSense breaks for Razor-views in MVC 3-applications in Visual Studio 2010. This is stated in the release-notes, but nobody usually reads those.

This time the solution to the problem are actually listed in those release-notes. You need to the explicitly state the version-numbers of the references in your web.config.

Add a new appSettings-entry for explicitly stating the version of WebPages to use:

<appSettings>
    <add key="webpages:Version" value="1.0.0.0"/>
    <!-- ... -->
</appSettings>

Then you have to edit your .csproj-file, where you need to find your references to System.Web.WebPages and System.Web.Helpers and makes sure they have the explicit version-numbers like this:

<Reference Include="System.Web.WebPages, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/> 
<Reference Include="System.Web.Helpers, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />

Hopefully this will be resolved in the final version of MVC 4 or maybe the case is that the references to versions in Razor v1 were just too loose in MVC 3-projects.