Deploying ASP.Net MVC 5 on Windows Server 2008

December 5, 2014

Developing an MVC application in Visual Studio 2013 (Update 3), I needed to install a demo on a Windows 2008 server.

Since Server 2008 ships with .Net 3, we first need to install .Net 4.5.1, either from the Visual Studio download page, or from MSDN.

After the required reboot and setting up a web application in IIS, browsing to the new site resulted in HTTP errors 403 (refers to directory browsing) and 404 (when navigating to a specific controller action).

Luckily, this issue could be solved by re-adding <modules> to the <system.webServer> section (found on SO):

<system.webServer>
  <modules>
    <remove name="UrlRoutingModule-4.0" />
    <add name="UrlRoutingModule-4.0" 
        type="System.Web.Routing.UrlRoutingModule" 
        preCondition="" />
  </modules>
</system.webServer>

After editing the web.config, the web application could be accessed, but all CSS and JavaScript requests, which are served using Bundling and Minification, would result in a 404.

Again, another module wanted to be included

      <remove name="BundleModule" />
      <add name="BundleModule" type="System.Web.Optimization.BundleModule" />

Finally, the web application looked as expected, so I logged in, and

No owin.Environment item was found in the context.

The internets are full of helpful tips to add

<add key=”owin:AppStartup” value=”[Namespace].Startup, [AssemblyName]” />

but that did not change anything. What really solved that last problem was to add the attribute

<modules runAllManagedModulesForAllRequests="true" />

in web.config.

In the end, the web.config section looks like this

  <system.webServer>
    <modules  runAllManagedModulesForAllRequests="true">
      <remove name="FormsAuthentication" />
      <remove name="UrlRoutingModule-4.0" />
      <add name="UrlRoutingModule-4.0"
          type="System.Web.Routing.UrlRoutingModule" 
          preCondition="" />
      <remove name="BundleModule" />
      <add name="BundleModule" 
          type="System.Web.Optimization.BundleModule" />
    </modules>

Remove Unused References with Visual Studio 2013

December 3, 2014

My favorite reference removal tool, Reference Assistant, only target Visual Studio 10 (2010) and 11 (2012), according to the description.

To install it in VS 2013, you need to follow the tips given on the Q&A tab of the assistant’s page on the Visual Studio Gallery:

So, the manifest file in this extension has a typo, which is why it wont install in VS2013. Change the vsix file to .zip, unzip it, edit the manifest file for the installationtargets from “[11.0,12.0)” to “[11.0,12.0]” and save it. Select all the files and zip it up. Rename the zip file to .vsix again and install.

If you follow those instructions literally,

  • rename the .vsix to .zip
  • unzip the .zip
  • edit the extension.vsixmanifest file
  • replace every instance of
InstallationTarget Version="[11.0,12.0)"

with

InstallationTarget Version="[11.0,12.0]"
  • save the file
  • zip all files
  • rename the .zip to .vsix

then the modified vsix can be installed in VS2013.

When I first tried it (by not following exactly), I simply dragged the .vsixmanifest file out of the .zip, edited it, and then moved it back into the .zip using Windows Explorer, I actually received the error message reported in the Q&A:

Microsoft.VisualStudio.ExtensionManager.InvalidExtensionPackageException:
The file is not a valid VSIX package.
---> System.IO.FileFormatException: File contains corrupted data.

Good to have the tool in the latest version of VS as well ;)


Fixing “The type ‘System.Web.Mvc.***’ is defined in an assembly that is not referenced.”

November 19, 2014

In Visual Studio 2010, I tried to compile an ASP.Net MVC 3 project that I have been working on for months, and suddenly received the error messages

The type ‘System.Web.Mvc.IAuthorizationFilter’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Web.Mvc, Version=3.0.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35′.

The type ‘System.Web.Mvc.FilterAttribute’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Web.Mvc, Version=3.0.0.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35′.

Turns out that by installing Visual Studio 2013 (or one its product updates) switches from 3.0.0.0 to 3.0.0.1, as a quick glance in the .csproj reveals:

<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, 
    PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />

versus

<Reference Include="System.Web.Mvc, Version=3.0.0.1, Culture=neutral, 
    PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />

By removing the reference and re-adding it, the solution compiled again successfully.


Custom XSD Validation in Visual Studio 2013

November 6, 2014

We developed an XSD schema, and wanted to create valid .cshtml markup using Visual Studio.

Based on tips found on the internet, I managed to get this working on VS2010 (sorry, didn’t write about it ;) ), but for VS2013, the solution seems to be different again.

Here’s how I managed to get custom XSD validation in VS2013:

  • Put a copy of your XSD in the directory
C:\Program Files[ (x86)]\Microsoft Visual Studio 12.0\Common7\Packages\schemas\html
  • Open regedit.exe and navigate to the key
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0_Config\Packages\{1B437D20-F8FE-11D2-A6AE-00104BCC7269}\Schemas

This reg key holds all schemas for the VS “package” Visual Studio HTM Editor Package”.

The value of “File” is the relative path to the .xsd, in our case “html\my.xsd”.

  • Add a string named “Friendly Name”

The value of “Friendly Name” is the name to be displayed in the validation settings.

  • Add a DWord named IsBrowseable

Not sure whether this is required, but HTML5 and XHTML5 also have it. Set its value to 1.

Alternatively, you can also create a .reg file, set the values according to your environment, and import using regedit:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0_Config\Packages\{1B437D20-F8FE-11D2-A6AE-00104BCC7269}\Schemas\http://tempuri.org/my.xsd]
"File"="html\\my.xsd"
"Friendly Name"="My Schema"
"IsBrowseable"=dword:00000001

Start Visual Studio 2013, and navigate to Tools, Options, Text Editor, HTML (Web Forms). Or simply type “valid” in the search box of the Options dialog.

You will find your entry “My Schema” in the dropdown list “Target when no doctype found:”.

If you only want to edit files confirming to your schema, then select it here.

Otherwise, close the dialog, and right-click the toolbar (right below the menu bar) and check the item “HTML Source Editing”. Now the toolbar will also contain the Target Schema selection dropdown.

BUT: If you open a .cshtml by double-clicking, the source will be displayed, but the Target Schema dropdown is inactive!

The reason is that, whoever invented this whole thing, there is a difference between “HTML Editor” and “HTML (Web Forms) Editor”!

Right-click the .cshtml file, and select “Open With…”. In my installation, HTML Editor is the default for .cshtm, but you can set the Web Forms editor as default using the, uhm, “Set as Default” button.

So now, either way you open the .cshtml in the “HTML (Web Forms) Editor”, the Target Schema selection dropdown is now active, and your custom schema can be selected for validation.

Unfortunately, Razor does not seem to be supported in the Web Forms Editor (high-lighting etc), so you need to choose between Razor-enabled unvalidated or Razor-disabled validated editing. Really?

Sources: SO, AngularJS, MSDN Social.


Browser Screenshot Tools

October 16, 2014

In my previous blog on browser screenshot extensions I did not cover Internet Explorer.

For two reasons: I do not use IE frequently, and therefore I had no experience with screenshot add-ons or plugins.

But now I across a screenshot tool called Greenshot. It’s not a browser extension, but rather a stand-alone program sitting in the Windows Toolbar, which lets you take a screenshot of the current window.

It offers special commands for IE, so that it also scrolls IE’s windows while taking a screenshot.

The default file name is derived from the window’s title and the current timestamp, but the file name format can be configured, and the file name can be changed in the File Save dialog.


Some Facebook Javascript Bookmarklets

September 10, 2014

Bookmarklets are pieces of JavaScript code that are stored as bookmarks in your browser, and execute locally (i.e. inside the downloaded page) as the bookmark is clicked.

Using the Facebook Graph API, you can take a look “behind the scenes” to retrieve the raw information of what is being displayed when you browse Facebook.

Requests under the URL http://graph.facebook.com/ return JSONified data about the requested object, which is identified by it’s ID.

Posts and Threads

Let’s look at threads (posts) and their IDs. There are a couple of ways the thread ID is stored in the thread URL, depending on where it is posted (page, group) and how you browse it (permalink or notification):

https://www.facebook.com/[name]/posts/[thread id]
https://www.facebook.com/groups/[group id]/permalink/[thread id]/
https://www.facebook.com/photo.php?fbid=[thread id]&set=[...]

Since the thread ID is numeric, a simple regex \d+ would be sufficient to retrieve it. However, group IDs may also be numeric, and names may contain digits.

After a bit of experimenting, the regex that I came up with to extract the thread ID from a Facebook URL, is

(/[\/=](\d+)[&\/]?/.exec(window.location.toString().replace(/\/groups\/\d+\//),""))[1]

Using this regex, we can now craft a JavaScript routine to open a new window containing the Graph API result:

window.open("http://graph.facebook.com/" +
    (/[\/=](\d+)[&\/]?/.exec(window.location.toString().replace(/\/groups\/\d+\//),""))[1] +
    "/comments", "_blank")

and create a bookmark for it. Since this WordPress installation does not allow to include bookmarklet links, you need to

  • Create a bookmark in your browser
  • Give it a name, such as “View Comments in FB Graph”
  • Set the URL or location to
javascript:window.open("http://graph.facebook.com/" + (/[\/=](\d+)[&\/]?/.exec(window.location.toString().replace(/\/groups\/\d+\//),""))[1] + "/comments", "_blank")
  • Click OK

But this does not give you the contents of the whole thread, just the comments.

To retrieve the whole post, we can use the Graph API Explorer.

The Graph API Explorer retrieves the details of a Facebook object, such as a post or thread, using the URL

https://developers.facebook.com/tools/explorer/?method=GET&path=[object id]

So, as we know how to extract the thread ID from a FB URL, let’s create a bookmarklet with the URL

javascript:window.open("https://developers.facebook.com/tools/explorer/?method=GET&path="+ (/[\/=](\d+)[&\/]?/.exec(window.location.toString().replace(/\/groups\/\d+\//,"")))[1], "_blank")

This opens the Graph Explorer with the desired ID. Click Submit to retrieve the data. Probably you need to click Get Access Token first.

Remove the Right Column

If you want to take screenshots of Facebook pages, you probably want to remove the right column before screenshotting, since it only expands the image, but does not include the content you want to save.

The top-most HTML container for right column content is called “rightCol” (yes, surprising).

To remove it from display, simply add this code to a bookmarklet:

javascript:var rc=document.getElementById("rightCol");rc.parentElement.removeChild(rc);

Clean up the Likes Page

To get a screenshot of “selected” Likes on a Like Page, there is a way to delete the Likes we don’t like (haha).

Simply scroll down until the list of likes is complete, then run this bookmarklet:

javascript:var li=document.getElementsByClassName("_5rz");for(var i=0;i<li.length;i++){var l=li[i];l.onclick=(function(el){return function() { el.parentElement.removeChild(el);return false;};})(l);}

Now clicking on a Like preview image will remove the entry from the list, allowing you to retain only the desired entries, ready to screenshot.


Capturing Awesomium Requests and Responses

September 2, 2014

The Awesomium browser controls provides a set of events that the hosting application can handle, but there is (currently, as of 1.7.4.2) there is no way to access the underlying HTTP requests and responses.

There are a couple of questions on SO that try to solve this problem, such as

which all hint to use the FiddlerCore library to make the application hosting the browser control also act as proxy for this control.

By using the proxy functionality of Fiddler and handling its events it is possible to access the HTTP request and response, and, for example, log data retrieved in AJAX calls. This answer on SO shows how Awesomium’s proxy settings are defined.

Since not all code samples on SO work with the current Awesomium version 1.7.4.2, here my solution based on the articles above.

In the App class (App.xml.cs), FiddlerCode must be initialized.

  public partial class App : Application
  {
    log4net.ILog logger;

    protected override void OnStartup(StartupEventArgs e)
    {
      logger = log4net.LogManager.GetLogger(typeof(App));
      SetupInternalProxy();
      base.OnStartup(e);
    }

    private void SetupInternalProxy()
    {
      FiddlerApplication.AfterSessionComplete += 
        FiddlerApplication_AfterSessionComplete;
      FiddlerApplication.Log.OnLogString += 
        (o, args) => logger.Warn(args.LogString);

      FiddlerCoreStartupFlags oFCSF = FiddlerCoreStartupFlags.Default;
      //this line is important as it will avoid changing the proxy for the whole system.
      oFCSF = (oFCSF & ~FiddlerCoreStartupFlags.RegisterAsSystemProxy);

      FiddlerApplication.Startup(
        0,
        oFCSF
        );
    }

This is also the location to analyze requests and responses. In the sample, jQuery JSON-responses are deserialized into C# objects

    private void FiddlerApplication_AfterSessionComplete(Session oSession)
    {
      var resp = oSession.oResponse;
      var ct = resp.headers["Content-Type"];

      if (ct.Contains(';'))
        ct = ct.Split(";".ToCharArray())[0];

      var req = oSession.oRequest;
      
      switch (ct)
      {
        case "text/html":
          // do something
          break;

        case "application/json":
          var json = oSession.GetResponseBodyAsString();
          if (json.StartsWith("jQuery"))
          {
            json = json.Substring(json.IndexOf('(') + 1);
            json = json.Substring(0, json.Length - 2);

            // deserialize C# object
            var content = JsonConvert.DeserializeObject(json);

            if (content != null)
            {
              var uri = new Uri(oSession.fullUrl);
              var q = HttpUtility.ParseQueryString(uri.Query);
              // parse query string
            }
          }
          break;

        default:
          // 
          break;
      }
    }

In the window hosting the browser control, we need to set the browser control’s proxy settings in the constructor:

public MyWindow()
{
  InitializeComponent();

  var pref = new awe.WebPreferences
  {
    ProxyConfig = "http://127.0.0.1:" + 
      FiddlerApplication.oProxy.ListenPort.ToString(),
    Plugins = false,
  };
  this.webControl.WebSession = awe.WebCore.CreateWebSession(pref);
}

That’s it ;)


Follow

Get every new post delivered to your Inbox.

Join 76 other followers