Quantcast
Channel: ASP.NET Blog
Viewing all 7144 articles
Browse latest View live

Make jQuery UI and Bootstrap 2 work together in MVC template

$
0
0

In the VS2013 preview MVC5 template, we included Bootstrap and jQuery UI together in the same project. However, some themes of jQuery UI (1.8.24 in the project template) is conflicting with Bootstrap (version 2.3.1 in the project template), especially for button. We have seen at least one such question in our forum.

Let’s create a test project first to see the effect.

1. File->New Project, choose Templates->Web->ASP.NET Web Application, select MVC, click Create Project

2. Right click project and choose “Manage NuGet Packages”, go to “Updates” tab, and update “jQuery UI (Combined Library)” to the latest version (1.10.3 at the time of writing)

3. Change the App_Start/BundleConig.cs file to include the jQuery UI js file.

Code Snippet
  1. bundles.Add(newScriptBundle("~/bundles/jqueryUI").Include(
  2.                         "~/Scripts/jquery-ui-{version}.js"
  3.                         ));

4. Change the Views/Shared/_Layout.cshtml file to include the style and script bundles. Note we are letting jQuery UI script to overwrite bootstrap. (Will show difference later)

Code Snippet
  1. @Styles.Render("~/Content/css")
  2. @Styles.Render("~/Content/themes/base/css")
  3. @Scripts.Render("~/bundles/modernizr")

 

Code Snippet
  1. @Scripts.Render("~/bundles/jquery")
  2. @Scripts.Render("~/bundles/bootstrap")
  3. @Scripts.Render("~/bundles/jqueryUI")
  4. @RenderSection("scripts", required: false)

 

5. Add the following test code to the end of Views/Home/Index.cshtml file

Code Snippet
  1.  
  2. <divclass="row">
  3.     <buttonid="jQueryUIButton"class="btn btn-info">BootStrap and JQueryUI</button>
  4.     <buttonclass="btn btn-info">BootStrap only</button>
  5.     <buttonid="jQueryUIButton2">JQueryUI only</button>
  6.  
  7.     <inputid="jQueryUISubmitButton"class="btn btn-info"type="submit"value="Input BootStrap and JQueryUI"/>
  8.     <inputclass="btn btn-info"type="submit"value="Input BootStrap only"/>
  9.     <inputid="jQueryUISubmitButton2"type="submit"value="Input JQueryUI only"/>
  10.  
  11.     <aid="jQueryUIAnchor"class="btn btn-info"href="#">anchor Bootstrap and JQueryUI</a>
  12.     <aclass="btn btn-info"href="#">anchor Bootstrap only</a>
  13.     <aid="jQueryUIAnchor2"href="#">anchor JQueryUI only</a>
  14. </div>
  15.  
  16. @section Scripts {
  17.     <script>
  18.         $(function () {
  19.             $("#jQueryUIButton").button();
  20.             $("#jQueryUIButton2").button();
  21.             $("#jQueryUISubmitButton").button();
  22.             $("#jQueryUISubmitButton2").button();
  23.             $("#jQueryUIAnchor").button();
  24.             $("#jQueryUIAnchor2").button();
  25.         });
  26.     </script>
  27. }

 

6. Run it, you can see the fonts are very different between the “BootStrap and JqueryUI” elements and “BootStrap only” element.

clip_image002

7. The order of including the Bootstrap JavaScript file and the jQuery UI JavaScript file matters. If we change step 4’s script order to put Bootstrap after jQuery UI script:

Code Snippet
  1. @Scripts.Render("~/bundles/jquery")
  2. @Scripts.Render("~/bundles/jqueryUI")
  3. @Scripts.Render("~/bundles/bootstrap")
  4. @RenderSection("scripts", required: false)

Run it, you can see “anchor JQueryUI only” does not get changed to button.

clip_image003

jQuery UI Bootstrap” can be used to make step 6 results a little bit better.

8. Revert step 7, Go to http://addyosmani.github.io/jquery-ui-bootstrap/ and download the latest archive, unzip the archive, locate “css/custom-theme” folder. Drag and drop images folder and latest jquery-ui-*.custom.css and jquery.ui.*.ie.css files to the project Content folder in solution explorer.

clip_image004

9. Add the following bundle in App_Start/BundleConig.cs

Code Snippet
  1. bundles.Add(newStyleBundle("~/Content/jqueryUIBootstrapCSS").Include(
  2.       "~/Content/jquery-ui-1.10.0.custom.css",
  3.       "~/Content/jquery.ui.1.10.0.ie.css"
  4.   ));

10. Change the CSS include in Views/Shared/_Layout.cshtml:

Code Snippet
  1. @Styles.Render("~/Content/css")
  2. @Styles.Render("~/Content/jqueryUIBootstrapCSS")
  3. @*@Styles.Render("~/Content/themes/base/css")*@
  4. @Scripts.Render("~/bundles/modernizr")

 

11. Run it.

clip_image005

12. Do the same as step 7, we will get the exact same output as step 7, which is:

clip_image006

From the above experiment, you can decide which combination of jQueryUI, BootStrap you'd like to use in your web project.

I also tried Bootstrap 3 RC1 with jQuery UI 1.10.3 in a sample website and the result is the same:

clip_image008


Use SignalR Sample Nuget package in VS2013 Preview MVC 5 Project

$
0
0

We received feedback that the current 1.2 version SignalR sample Nuget package doesn’t work in an MVC 5 project by default. Here are the repro steps and the necessary change to make it work.

1. Create a C# MVC 5 project in VS2013 Preview

clip_image002

clip_image004

2. Install Microsoft.AspNet.SignalR.Sample NuGet package

clip_image006

3. This installs SignalR package version 1.1.3. In the SignalR.Sample/StockTicker.html file, the script link still links to 1.1.2, so change it to 1.1.3 first.

<script src="../Scripts/jquery.signalR-1.1.3.js"></script>

4. Run the application (I was using windows 8.1 preview with IE11), and get a JavaScript error:

clip_image008

5. What happened here is due to a bug in the 1.1.0-beta2 release of the Microsoft.Owin.Host.SystemWeb package, which will be fixed in future release. To work around this, the best way is to upgrade SignalR 1.1.3 to the latest 2.0 beta2 release.

6. Read http://www.asp.net/vnext/overview/latest/release-notes#TOC13 to understand the migration process from SignalR 1.x to 2.0. Migrating the sample package is a little bit simpler. First, upgrade the SignalR NuGet package to 2.0 Beta2 (select Include Prerelease in the drop-down at the top of the dialog):

clip_image010

7. A readme.txt file pops up talking about the hub registration. Compile to see the expected error message:

clip_image012

8. Delete App_Start/RegisterHubs.cs as it’s no longer used

9. In the root startup.cs file, add app.MapHubs(); in the Configuration method.

clip_image013

10. Change SignalR.Sample/StockTicker.html script link to 2.0

<script src="../Scripts/jquery.signalR-2.0.0-beta2.js"></script>

11. Run the html page, now you see that the SignalR sample works correctly.

clip_image014

The StockTicker sample package is open sourced at https://github.com/SignalR/SignalR-StockTicker. Currently it supports 1.x only, as SignalR 2.0 has not reached RTM yet. The sample will probably get updated by SignalR 2.0 RTM time.

Install MVC4 HotTowel SPA NuGetNuGet package in One ASP.NET Web API Project in VS2013 Preview

$
0
0

I was trying to install MVC4 HotTowel SPA package (MVC4 and Razor v2) on a VS2013 Preview One ASP.NET Web API Project (MVC5 and Razor V3). I blindly let the NuGetNuGet package overwrite all my files including the Views\web.config file, which caused some compatibility problems.

This is what I did:

1. Create a Web API One ASP.NET project

clip_image002

2. Manage NuGet packages, find HotTowel: ASP.NET MVC SPA Template package, click Install.

clip_image004

3. I chose “Yes to All” when prompted for file overwriting. I should have chosen “Yes” and “No” buttons for each file overwriting warning dialog in order to prevent overwriting Views\web.config.

4. CTRL-F5 to run the application, I get the following error in IE:

[A]System.Web.WebPages.Razor.Configuration.HostSection cannot be cast to [B]System.Web.WebPages.Razor.Configuration.HostSection. Type A originates from 'System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' in the context 'Default' at location 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.WebPages.Razor\v4.0_2.0.0.0__31bf3856ad364e35\System.Web.WebPages.Razor.dll'. Type B originates from 'System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' in the context 'Default' at location 'C:\Users\xinqiu\AppData\Local\Temp\Temporary ASP.NET Files\root\3c4ae604\700fa44c\assembly\dl3\8be5ce88\7c28f49b_e28fce01\System.Web.WebPages.Razor.dll'.

5. It took me quite a while to figure out what was wrong since the ~/web.config is correct, until I realized there is also a Views/web.config file. After I manually corrected the Views/web.config file to match a normal Web API project Views/web.config file, the application works correctly with HotTowel features.

Later I found this experience matches the following StackOverflow question about migrating an MVC4 project to MVC5: http://stackoverflow.com/questions/17454852/upgrading-from-mvc4-to-mvc5-pre-release. So hopefully my simple mistake might have some value to be shared.

Accessing the ASP.NET Web Configuration Tool in Visual Studio 2013

$
0
0

As many of you have noticed, the option to select “ASP.Net Web Configuration Manager” is no longer in Visual Studio 2013 Preview. This is due to the removal of the Visual Studio Development Server (or Cassini) from the product. However, we understand that many people have gotten used to using the Tool, and so here are the steps by which you can still run the manager. Note that these instructions only work for sites running on the .NET Framework 4.0 and above.

  1. Open the Command Prompt (not as administrator)
  2. Navigate to the folder where IIS Express is installed on your machine.
  3. In the command line spin up a IISExpress site with the following prompt: “iisexpress.exe /path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\ASP.NETWebAdminFiles /vpath:”/ASP.NETWebAdminFiles” /port:[port] /clr: 4.0 /ntlm” using the following values for the [param]:
    1. [port] – any port you have free in IISExpress (I use 8082 in the example below)
  4. This should launch an IISExpress instance of the Configuration Manager Site<br/>clip_image002
  5. Open your browser
  6. In the URL enter the following “http://localhost:8082/asp.netwebadminfiles/default.aspx?applicationPhysicalPath=[appPath]&applicationUrl=/” substituting the [appPath] with the absolute path to the Visual Studio Project folder with the solution file in it.

Congratulations, you now have your ASP.net Web Site Adminstration Tool running as before.

Web Publishing a simpler way to exclude files/folders from being published

$
0
0

I’ve written a fewblog posts on how to exclude files from publishing/packaging. In each of these posts you’d have to be familiar with MSBuild and the Web Publish process. I’ve been looking for a much simpler way to exclude files/folder from publishing.

When using git you can easily exclude files and folders using a .gitignore file. Inside the .gitignore file on each line you can add a pattern that matches files/folders to be excluded from the repository. For example take a look at the sample .gitignore file below.

# Folders to ignore #
OutputRoot/
TestResults/
bin/
obj/
BuildOutput/

# Known files to ignore always #
*.suo
*.user
~*.docx
*.metaproj*

In the .gitignore file above you can see how easy it is to exclude files and folders from publishing.

I thought it would be cool if we had the ability to exclude items from publishing this easily. Now we do!

I’ve created a NuGet package which solves this exact issue. With a web project opened try out the following.

  1. From the Package Manager console execute Install-Package PublishIgnore –pre
  2. Edit the publish.ignore file to add files/folders to be excluded
  3. Publish

You should see that the publish operation skips the files and folders which match the patterns in publish.ignore.

Some notes regarding the implementation here. The publish.ignore file is only supported at the root folder. .gitignore has support to drop .gitignore files in the root as well as subfolders. Currently publish.ignore is not supported in sub folders. This is something that can be implemented if there is enough interest here.

You may be wondering why I named the file “publish.ignore” instead of .publishignore. The reason for this is that on Windows it is difficult to create file names which do not have a string prefixing the extension. You can create these files through the command line, but not through Windows Explorer or VS.

This project is all open source at https://github.com/ligershark/publish-ignore. If you have any problems you can file an issue there, and if you like you can contribute to the code as well!

If this is something that you’d like to see in the box please email me and let us know SayedHa@microsoft.com

 

Thanks,
Sayed Ibrahim Hashimi | @SayedIHashimi

Update: Knockout IntelliSense Highlight Bug Fix

$
0
0

In an earlier blog post on June 24th entitled Knockout IntelliSense Highlighting Bug Fix I described a bug fix in the Knockout IntelliSense feature. In that post I recommended installing Windows Azure SDK for .NET (VS 2012) – 2.0 to acquire the fix since it did not make it into any of the Visual Studio Updates for 2012.

Several customers have asked if there’s a lighter-weight solution to acquiring this fix. This article described the minimal install required to improve Knockout highlighting.

What Version of WTE Do I Have?

To determine what version of WTE is installed, select “About Microsoft Visual Studio” from the HELP menu in Visual Studio 2012. Scroll down the Installed Products list and find “Web Developer Tools”:

RTM

Web Developer Tools 1.0.30710.0

 

No Knockout IntelliSense

VSU 1

Web Developer Tools 1.0.30710.0

KB2707250

No change to WTE

VSU 2

Web Developer Tools 1.2.40308.0

KB2797912

Knockout IntelliSense added

VSU 3

Web Developer Tools 1.2.40308.0

KB2835600

No change to WTE

WTE 1.3

Web Developer Tools 1.3.40412.0

 

KO Highlighting bug fixed

While we referred to the release as WTE 1.3 internally and as “Web Developer Tools 1.3.40412.0” in the About Box, its official branding was “Microsoft Web Developer Tools 2012.2.1 for Visual Studio 2012.” We regret any confusion the naming convention may cause.

To retrieve and install the appropriate release:

1. Using your favorite browser, download the installer for your product and locale from the table below.

2. On a machine with Visual Studio 2012 or VS Express for Web 2012 installed, close all instances of the product.

3. Run the MSI file downloaded and select “Install.”
image

4. Run Visual Studio or VS Web Express and check the Web Developer Tools version in “About Microsoft Visual Studio.” It should be:
image

Visual Studio 2012 Professional, Premium or Ultimate Installer by Locale:

ENU 

 http://go.microsoft.com/fwlink/?LinkID=298622&amp;clcid=0x409 

JPN 

 http://go.microsoft.com/fwlink/?LinkID=282228&amp;clcid=0x411 

CHS 

 http://go.microsoft.com/fwlink/?LinkID=282228&amp;clcid=0x804 

DEU 

 http://go.microsoft.com/fwlink/?LinkID=282228&amp;clcid=0x407 

FRA 

 http://go.microsoft.com/fwlink/?LinkID=282228&amp;clcid=0x40c 

CHT 

 http://go.microsoft.com/fwlink/?LinkID=282228&amp;clcid=0x404 

ESN 

 http://go.microsoft.com/fwlink/?LinkID=282228&amp;clcid=0x40a 

ITA 

 http://go.microsoft.com/fwlink/?LinkID=282228&amp;clcid=0x410 

KOR 

 http://go.microsoft.com/fwlink/?LinkID=282228&amp;clcid=0x412 

RUS 

 http://go.microsoft.com/fwlink/?LinkID=282228&amp;clcid=0x419 

VS Express for Web 2012 Installer by Locale:

ENU 

 http://go.microsoft.com/fwlink/?LinkID=282231&amp;clcid=0x409 

JPN 

 http://go.microsoft.com/fwlink/?LinkID=298623&amp;clcid=0x411 

CHS 

 http://go.microsoft.com/fwlink/?LinkID=282231&amp;clcid=0x804 

DEU 

 http://go.microsoft.com/fwlink/?LinkID=298623&amp;clcid=0x407 

FRA 

 http://go.microsoft.com/fwlink/?LinkID=298623&amp;clcid=0x40c 

CHT 

 http://go.microsoft.com/fwlink/?LinkID=282231&amp;clcid=0x404 

ESN 

 http://go.microsoft.com/fwlink/?LinkID=282231&amp;clcid=0x40a 

ITA 

 http://go.microsoft.com/fwlink/?LinkID=282231&amp;clcid=0x410 

KOR 

 http://go.microsoft.com/fwlink/?LinkID=282231&amp;clcid=0x412 

RUS 

 http://go.microsoft.com/fwlink/?LinkID=282231&amp;clcid=0x419 

NuGet 2.7 Released

$
0
0

The NuGet team is excited to announce NuGet 2.7 release, for details please see the release notes published on docs.nuget.org.

NuGet 2.7 Features

  1. Package Restore by Default (with implicit consent)

    1. Automatic Package Restore in Visual Studio
    2. Simplified Package Restore from the Command-Line
  2. Project Retargeting and Upgrade Build Errors/Warnings

  3. NuGet Configuration Defaults

  4. Renaming the Default Package Source

  5. Performance Improvements

  6. New Extensibility APIs

  7. Development-Only Dependencies

Note that with NuGet 2.7, we have removed support for Visual Studio 2010 Express for Windows Phone due to technical limitations related to the new automatic package restore. A separate download is available for that version of Visual Studio and it can be found on the NuGet 2.7 downloads page on CodePlex.

Visual Studio 2013

NuGet 2.7 is the version of NuGet that will be included in Visual Studio 2013, with the exception of minor updates such as refreshed localization. When those updates are completed, we will republish NuGet 2.7, but no new features will be added.

Known Issues

There are two known issues with nuget.exe restore with the 2.7 release, and these will be fixed soon and the nuget.exe download will be updated along with the NuGet.CommandLine package.

  1. New package restore doesn’t work on Mono when using SLN file
  2. New package restore doesn’t work with Wix projects

Introducing NuGet Concierge

$
0
0

Twelve weeks ago, the Azure Applications Platform & Tools team welcomed us, three college sophomores, Jaspreet Bagga, Jeremiah Jekich, and Melissa McNeill, to Microsoft.

As Explorer Interns, we were given the opportunity to experience the three primary disciplines here at Microsoft: Program Manager, Software Development Engineer, and Software Development Engineer in Test. Rotating positions throughout the course of development, we were able to experience what life is like working in the developer tools division. We were given the opportunity to contribute to one of Visual Studio’s great tools, the NuGet package manager.

Package Discovery

For developers, discovering NuGet packages can be a daunting process. The best way to do so is either via word of mouth or online search. However, your friends aren’t always available when you’re looking for a new package at 3:00 in the morning. You could try to search online, but you’d need to spend unnecessary amounts of time sifting through the results before finding a package that may be helpful. We recognize that this time is better spent actually developing software. We wanted to create an accessible service to deliver package recommendations using real world data about how developers use packages.

clip_image002

NuGet Concierge

Thus was born NuGet Concierge, a package recommendation service that recommends packages to developers based on the packages currently being used in their project. We envisioned developers being able to upload their project’s packages.config file to the NuGet Concierge website, which would then present them with a list of packages they may find useful. Something along the lines of “Most projects that use Package A also use Package B.”

So, at the beginning of the summer, we put out a call to the community via Twitter, asking for developers to upload their projects’ packages.config files to help seed our newly conceived recommendation service. We asked, and you delivered! Armed with a collection of over 350 packages.config files, we set to work bringing NuGet Concierge to life.

Implementation

The first step was to translate the collected .config files into a structure that would allow us to analyze the relationships between packages. How often are individual packages used? But, more importantly, how are packages used together?

So, we took the community’s .config files and parsed them, using them to construct a graph. In doing so, we tracked the number of times a package was used, a value we referred to as the package’s “popularity.” We also tracked how many times two packages were used together, which we referred to as the packages’ “pairing frequency.”

Determining Relationships

Let’s say we have two packages, EntityFramework and jQuery. By looking at our graph, we know the popularity of EntityFramework and the popularity of jQuery, as well as the pairing frequency between the two. In order to determine the strength of EntityFramework’s relationship with jQuery, we take the pairing frequency between the two and divide it by the popularity of EntityFramework. This gives us the percentage of time EntityFramework is used with jQuery. If we want to know how strongly jQuery is associated with EntityFramework, we simply take the pairing frequency and divide it by the popularity of jQuery.

clip_image004

Making Recommendations

Suppose a developer has a packages.config file that contains knockoutjs. In order to make recommendations, we look at all packages used with knockoutjs that are not currently in use in the developer’s project. In this case, let’s say knockoutjs is associated with Newtonsoft.Json and Modernizr at association strengths of 91% and 87% respectively. We would recommend Newtonsoft.Json first, followed by Modernizr.

clip_image006

With NuGet Concierge, we made every effort to enable improvements over time. When users upload their packages.config file, we present them with the option to contribute their file to the NuGet Concierge dataset. This increases the pool of .config files from which we generate our graph. This means that our recommendations become more accurate the more NuGet Concierge is used.

Additionally once users are presented with recommendations, they have the option to “Like” or “Dislike” each recommendation by giving it a thumbs up or a thumbs down. This information gets stored and allows us to analyze the usefulness of the recommendations we are making. If we find some packages are being recommended at a high association strength, but most users deem them unhelpful, we can adjust the system to recommend the packages at more appropriate strengths. Likewise, we can give a strength boost to packages recommended at low association strengths but deemed helpful by the community.

clip_image008

NuGet Concierge’s Potential

When looking to the future, we see NuGet Concierge as a fully integrated part of NuGet, having a presence in the Gallery, Visual Studio’s Manage NuGet Packages dialog, and the Package Manager Console. The greatest part of NuGet Concierge is the data powering it. The ability to reference real data about how packages are actively used together opens up a world of opportunities that can potentially help NuGet better serve developers.

Exploring Microsoft and NuGet

As Explorer Interns, we are proud to be able to say we helped pioneer a new feature of NuGet. Though NuGet Concierge is in its infancy, it is a service that can be utilized today. In line with the rest of NuGet, it is an open source project that can be contributed to by members of the community. The three of us have grown a lot as developers over the past three months, and it will be fun to watch NuGet Concierge grow as we continue with our education.

When we first arrived, we had no experience developing with web technologies or building developer tools. We have been repeatedly amazed by the breadth of technologies used in the web space, and it has been an honor to contribute to a team that helps improve developer experiences.

The Explore Microsoft Program and the Azure Applications Platform & Tools team provided us with an amazing opportunity to learn from the best and it was an invaluable experience that has inspired us to continue pursuing a future in technology and software development.


NuGet 2.7 Package Restore Tips

$
0
0

Since the release of NuGet 2.7 with Automatic Package Restore and implicit consent, many developers have adopted the new approach and provided some great feedback on their experiences. Based on that feedback, we have collected a set of tips to help you start using the new restore features.

Using Automatic Package Restore

Even though package restore consent is on by default, users still need to choose to omit their packages from source control before package restore is engaged. By default, source control systems will include the packages folder in your repository, and you need to take action to omit the packages from source control.

Git

Use the .gitignore file to ignore the packages folder. Adding a line that simply has "packages" on it will do the trick.

*.user
*.suo
bin
obj
packages

TF Version Control

Use a .nuget\NuGet.Config file to disable source control integration for the solution, as explained on the NuGet Config Settings document under the "Source control integration" section.  Using this approach, rather than cloaking the packages folder or otherwise ignoring it, NuGet knows to completely skip the call into Visual Studio to pend changes to the packages folder.

Here is what your .nuget\NuGet.Config file should look like to disable this integration.  Note that you won't be able to create the .nuget folder using File Explorer because it prevents the creation of folders that begin with a dot.  You will need to create the folder from a command prompt.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<solution>
<add key="disableSourceControlIntegration" value="true" />
</solution>
</configuration>

Migrating from MSBuild-Integrated Package Restore

If you have a solution that has previously enabled the MSBuild-Integrated Package Restore approach and you would like to migrate to use Automatic Package Restore, there are just a few steps you can take to smoothly make the switch.  The full walk-through is documented on the NuGet Docs site and it explains how to remove the unnecessary files from your solution and how to clean up your project files.

Package Restore with Team Foundation Build

Whether you're using TFS on-premises or you're using the Team Foundation Service, you can configure your Team Foundation Build to automatically restore packages as part of the build.  This can work with either Git or TF version control.

The documentation for how to configure your build can be found here: http://docs.nuget.org/docs/reference/package-restore-with-team-build

Package Restore Consent Errors

Some users reported that they were still seeing build errors indicating that package restore consent had not been given. When we made the package restore changes in NuGet 2.7, we identified one scenario where this would happen but determined we couldn't implement a fix and would rather have to document the scenario, cause and solution.

Scenario and Cause

In order to hit this problem, there’s a specific scenario you must be in. The scenario isn't extremely common, but we have already heard reports of it.

  1. Using a freshly built machine or a machine where Visual Studio was freshly installed
  2. NuGet has been upgraded to 2.7
  3. An existing solution is opened where the MSBuild-integrated package restore has already been enabled
  4. The MSBuild-integrated package restore was enabled before NuGet 2.7 was released

In this scenario, the solution contains a .nuget folder that has nuget.exe version 2.6 or earlier. In those versions of nuget.exe, package restore consent was OFF by default (hard-coded to false when not present in nuget.config). When building this solution in Visual Studio, NuGet identifies that the MSBuild-integrated package restore is enabled and therefore automatic package restore is skipped. Then the old nuget.exe kicks in for the package restore and it does not find package restore consent to be given, yielding the following build error:

Package restore is disabled by default. To give consent, open the Visual Studio Options dialog, click on Package Manager node and check ‘Allow NuGet to download missing packages during build.’ You can also give consent by setting the environment variable ‘EnableNuGetPackageRestore’ to ‘true’.

Solution

As explained on the Package Restore documentation, there are three ways to address this situation.

  1. Force save your NuGet settings with consent given. To do this, open Visual Studio’s options and under Package Manager, choose General. Uncheck and then re-check the boxes for consent and click OK. This forces your %AppData%\NuGet\NuGet.config file to be saved with consent explicitly given, allowing NuGet 2.6 and earlier to see that you've given consent.
  2. Update the version of nuget.exe in your .nuget folder. To do this, run nuget.exe update -self from your .nuget folder, which will download the latest version of nuget.exe and replace the version in the .nuget folder. The latest version of nuget.exe will infer consent to be ON even when not explicitly saved in the NuGet.config file.
  3. Migrate to Automatic Package Restore. For this approach, you would migrate from the MSBuild-integrated package restore to the Automatic Package Restore approach, following the documented walk-through.

Debug ScriptBundle results in 404 if virtualPath parameter contains a dot

$
0
0

I spent some time debuging a ScriptBundle problem last Friday and want to share my experience.

The original code in a MVC project App_Start/BundleConfig.cs file:

Code Snippet
  1. bundles.Add(newScriptBundle("~/bundles/jquery.signalR").Include(
  2.             "~/Scripts/jquery.signalR-{version}.js"));

And in a cshtml file, the bundle is included as:

Code Snippet
  1. @Scripts.Render("~/bundles/jquery.signalR")

In local IIS Express debugging mode, I found no problem. So I deployed to Azure to see if project works in real server. And to my surprise, it reported an error that SignalR is not loaded. The following image from the IE F12 developer tools shows a 404 is returned when getting /bundles/jquery.signalR.

clip_image001

To find out if bundling works locally, I changed project configuration to release, and changed web.config debug="true" to debug="false". Then running the site on IIS Express returns the same 404 as well.

I did a few searches in Bing. First, I went to MSDN documentation on ScriptBundle. Nothing there except I saw the parameter is named as “virtualPath”.

Later I found a forum question talking about IIS Virtual directory won’t work if it has a dot in the name. I also found a stackoverflow question which answer says remove the dot but gave a non-convincing reason. So the solution is to remove the dot from virualPath parameter, and it worked!

Further search for reason shows that IIS by default rejected URLs that have dot in path for security reasons. For example, in URLScan.ini downloaded from http://www.iis.net/learn/extensions/working-with-urlscan/urlscan-setup, it shows:

Code Snippet
  1. AllowDotInPath=0               ; If 1, allow dots that are not file
  2.                                ; extensions. The default is 0. Note that
  3.                                ; setting this property to 1 will make checks
  4.                                ; based on extensions unreliable and is
  5.                                ; therefore not recommended other than for
  6.                                ; testing.

 

In ISA server URLScan.ini documentation, it offers more explanation:

By default, this option is set to 0. If this option is set to 0, URLScan rejects any request that contains multiple periods (.). This prevents attempts to disguise requests for dangerous file name extensions by putting a safe file name extension in the path information or query string portion of the URL. For example, if this option is set to 1, URLScan might permit a request for http://servername/BadFile.exe/SafeFile.htm because it interprets it as a request for an HTML page, when it is actually a request for an executable (.exe) file with the name of an HTML page in the PATH_INFO area. When this option is set to 0, URLScan may also deny requests for directories that contain periods.

In summary, looks like for all the MVC/WebAPI routing, don’t put dot in any virtual path to avoid the above problem.

Announcing release of ASP.NET and Web Tools for Visual Studio 2013 RC

$
0
0

Announcing release of ASP.NET and Web Tools for Visual Studio 2013 RC

I’m excited to show the new features of the ASP.NET and Web Tools for Visual Studio 2013 RC. Click here to download and install the Visual Studio 2013 RC today. Please check http://www.asp.net/vnext for release notes, documentation, and tutorials. This blog includes both the new RC features and the features that already announced in the ASP.NET and Web Tools for VS2013 Preview that was released 2 months ago. We will have incoming blogs to talk about the features in detail.

Visual Studio Web Tooling Enhancements

One ASP.NET

We made a simple UI for creating projects that offer support for multiple ASP.NET frameworks (Web Forms, MVC, and Web API). New features are available for Web Forms that used to be offered only for MVC, such as automatic test project creation different authentication configurations.

clip_image002[5]

clip_image004[8]

Different authentication configurations can be chosen, and authentication works the same in all ASP.NET frameworks and in web hosting software other than IIS.

All of the ASP.NET project templates now use use Bootstrap to provide responsive design and theming capabilities. The Single Page Application template has been updated with support for OAuth 2.0 and a Web API based account controller that can be used from JavaScript and also from native mobile applications.

For more information about the new process for creating web projects, see Creating ASP.NET Web Projects in Visual Studio 2013 RC.

Browser Link – SignalR channel between browser and Visual Studio

A new feature, Browser Link, uses a SignalR channel between browsers and Visual Studio 2013 RC. It allows manually refreshing all connected browsers by clicking the toolbar refresh button. You can connect multiple browsers to your development site, including mobile emulators, and click refresh to refresh all the browsers all at the same time. In RC, we also introduced Browser Link Dashboard where you can refresh individual browser. You enable the Browser Link Dashboard from the refresh icon as shown in the following image:

clip_image005[7]

We also released API to write browser link extensions. Mads’ web essentials for Visual Studio 2013 (source) contains a few extensions that one can find really useful.

clip_image006[5]

In the Browser Link Dashboard, you can see each active connection listed under the Connections node. You can use the down arrow for each browser to choose a task, such as refresh to refresh each individual browser manually, or manual actions with the extensions that you’ve installed, such as “Design Mode”, “Inspect Mode”, “Snapshot Page”, “Start Recording” web essential extension commands.

clip_image007[7]

The Problems node lists the possible reasons why the browser link might not work and offers suggestions to correct the problem.

New HTML editor

In VS2013 RC, a new HTML editor is released for Razor files and HTML files. Web Forms .aspx, .master and user control .ascx files are still using the legacy editor for various reasons. The new HTML editor provides a single unified HTML5-based schema. It has some improvement such as automatic brace completion, jQueryUI and AngularJS attribute IntelliSense, attribute IntelliSense Grouping etc. In RC, we make CSS class attribute intelliSense working even if bundling and minification is used.

clip_image008[5]

The Tools\Options\Text Editors settings are different for legacy and new HTML editors. They are named “HTML” (for HTML files, Razor files, and Windows 8 Modern JavaScript apps) and “HTML (Web Form)” (for Web Forms files) respectively.

clip_image010[8]

Azure website tooling with Azure SDK 2.1

With installation of Azure SDK 2.1, you can create Windows Azure web sites from VS2013 RC’s server explorer.

clip_image011[5]

You can easily configure the website, add a new Web Site, and import the subscription file (which is used to publish to Windows Azure from the Visual Studio).

Scaffolding

VS 2013 RC has completely rewritten MVC Scaffolding. Please visit here for more information.

clip_image013[9]

We removed WebForm Scaffolding from this release because it's not ready yet. We’ll put the new bits in future release, possibly targeting update 1.

ASP.NET Framework Enhancements

ASP.NET MVC 5

MVC projects are now standard Web Applications and do not use their own project GUID. An MVC 5 project is created if the MVC checkbox is checked in the One ASP.NET new project dialog. For more information see Getting Started with ASP.NET MVC 5.

ASP.NET Web API 2

ASP.NET Web API 2 includes a variety of new features including:

· Attribute routing

· OData improvements

· Request batching

· Improved unit testability

· CORS

· Support for portable libraries

· OWIN integration.

For details on ASP.NET Web API 2 features, please see the RC release notes or refer to the ASP.NET Web API 2 documentation here.

ASP.NET SignalR

SignalR 2.0.0-rc1 is included with VS2013 RC. It includes support for MonoTouch and MonoDroid, portable .NET client, and the self-hosting package Microsoft.AspNet.SignalR.SelfHost, and it is backwards compatible for servers. For more SignalR 2.0.0-rc1 release notes, please visit http://www.asp.net/visual-studio/overview/2013/release-notes-(release-candidate)#TOC13 .

Entity Framework

Entity Framework 6.0.0-rc1 is included with VS2013 RC. See http://blogs.msdn.com/b/adonet/archive/2013/08/21/ef6-release-candidate-available.aspx for detail.

Microsoft OWIN Components

The Microsoft OWIN components (also known as the Katana project) integrates support for the Open Web Interface for .NET (OWIN), deep into ASP.NET. OWIN defines a standard interface between .NET web servers and web applications. Any OWIN based application or middleware can run on any OWIN capable host, including ASP.NET on IIS.

You host OWIN-based middleware and frameworks in ASP.NET using the Microsoft.Owin.Host.SystemWeb NuGet package. The Microsoft.Owin.Host.SystemWeb package has been enhanced to enable an OWIN middleware developer to provide hints to the SystemWeb server if the middleware needs to be called during a specific ASP.NET pipeline stage (ex during the authentication stage). The Microsoft OWIN Components also includes an HttpListener-based server, a self-host API and an OwinHost executable for running OWIN applications without having to create a custom host. With the OwinHost 2.0.0-rc1 NuGet package, VS2012 RC can now easily convert an IIS Express based WebAPI or SignalR project to a project that is run from OwinHost.exe.

clip_image015[9]

ASP.NET authentication is now based on OWIN middleware that can be used on any OWIN-based host. Microsoft OWIN Components includes a rich set of middleware components for authentication including support for cookie-based authentication, logins using external identity providers (like Microsoft Accounts, Facebook, Google, Twitter), and logins using organizational accounts from your on-premise Active Directory or Windows Azure Active Directory. Also included is support for OAuth 2.0, JWT and CORS. For more information see An Overview of Project Katana.

ASP.NET Identity

ASP.NET Identity is the new membership system for building ASP.NET applications. ASP.NET Identity makes it easy to integrate user specific profile data with the application data. With ASP.NET Identity you control the persistence model of your application. For example, you can store your user data in a SQL Server database or any other persistence store.

For information about using ASP.NET Identity with Individual User Accounts authentication, see http://www.asp.net/visual-studio/overview/2013/creating-web-projects-in-visual-studio#inauth.

NuGet

NuGet 2.7 is included with VS2013 RC. See http://docs.nuget.org/docs/release-notes/nuget-2.7 for more details.

Summary

Today’s Visual Studio 2013 RC has a lot of useful features for developers using ASP.NET. Read the release notes to learn even more, and install it today!

What is new in Browser Link with Visual Studio 2013 RC?

$
0
0

Over the last few months, the Browser Link team has worked on delivering these new features in the Visual Studio 2013 RC release:

  1. Browser Link Dashboard
  2. APIs for extension authoring

For those who are not familiar with Browser Link, please look at our introductory blog here.

Browser Link Dashboard

The Browser Link Dashboard is a tool window in VS that shows all active browser link connections.

You can invoke the dashboard by clicking on the little arrow next to the Refresh Linked Browser icon.

image

Clicking on the Browser Link Dashboard menu item will bring up the tool window.

As you can see in the image below, the dashboard shows all active connections related to your solution. These include connections that were opened via F5 (run with debugger), Ctrl+F5 (run), View in Browser or even just by opening any browser and pasting the url.

For example, in the image below, you can see that connections to About.aspx in IE, Chrome and IPad emulator are all listed in the Browser Link Dashboard. The connections also give you details of the url.

A Problems node exists to tell you if there is a problem. In our case, we are good as the debug flag is set to true and we are on a 4.5 project.

image

APIs for extension authoring

With the RC release, we now support the authoring of Browser Link Extensions via a public API. The rest of this post describes what a Browser Link Extension is and how you can write one.

A Browser Link Extension is a VS extension that will let you talk to all Browsers connected with any web project  that is open in Visual Studio. Your extension will have a CSharp part and a JavaScript part. The CSharp part is run in the context of Visual Studio. The Javascript part gets injected in the browser when a user makes a requests to that page. There are APIs on both sides that allow them to talk to each other.

Let us start off with writing a simple Browser link Extension.

To get started you will need the following:

1. Visual Studio Ultimate 2013 RC from here.

2. VSSDK from here.

3. The  Visual Studio Template for Browser Link Extension from the VS Gallery. This is available here.

Here is a step by step explanation of how to author a simple extension:

Step 1: Create a Browser Link Project by going to:

File –>New Project ->Visual C# –>Extensibility. Search for Browser Link Extension, select it and click the OK button.

image

Step 2: The project is created for you at this point.

Step 3: Open SimpleBrowserLinkProject.js under the scripts folder. Copy and paste the following. I have added a simple HelloWorld function that can be called from Visual Studio.

Code Snippet
  1. /// <reference path="../intellisense/browserlink.intellisense.js" />
  2.  
  3. (function (browserLink, $) {
  4.     /// <param name="browserLink" value="bl" />
  5.     /// <param name="$" value="jQuery" />
  6.  
  7.     function output(message) { // Helper for the 'greeting' function
  8.         alert(message);
  9.  
  10.         if (console) {
  11.             console.log(message);
  12.         }
  13.     }
  14.  
  15.     return {
  16.  
  17.         HelloWorld: function(message)
  18.         {
  19.             var topDiv = document.createElement("div");
  20.             topDiv.id = "SimpleDiv";
  21.             var textElement = document.createTextNode(message);
  22.             topDiv.appendChild(textElement);
  23.             $("body").prepend(topDiv);
  24.         }
  25.         ,
  26.         name: "SimpleBrowserLinkProject",
  27.  
  28.         greeting: function (message) { // Can be called from the server-side extension
  29.             output(message);
  30.         },
  31.  
  32.         onInit: function () { // Optional. Is called when a connection is established
  33.            
  34.         }
  35.     };
  36. });

Step 4: Open SimpleBrowserLinkProject.cs and copy and paste the following under OnConnected.

Code Snippet
  1. publicoverridevoid OnConnected(BrowserLinkConnection connection)
  2.         {
  3.             Clients.Call(connection,"HelloWorld", "This is a simple Browser link extension!!");
  4.         }

Step 5: Ctrl + F5 and this will open the experimental instance of Visual Studio. Now, Create a Web Application Project and View About.aspx in IE and Chrome. In each of these new connections, we are calling the javascript function “HelloWorld” which adds a div at the top of your page. 

image

This is a simple extension which shows how VS can talk to all browsers.

Step 6:  To talk from the browser to VS, make the following changes. Copy and paste this code into your OnInit function in SimpleBrowserLinkProject.js.

Code Snippet
  1. onInit: function () { // Optional. Is called when a connection is established
  2.             browserLink.call("SendText", "Hello from JS to VS")
  3.         }

Step 7: In your SimpleBrowserLinkProject.cs file you should have a SendText method which has a BrowserLinkCallBack Attribute. This attribute suggests that this can be called from JavaScript.

Code Snippet
  1. [BrowserLinkCallback] // This method can be called from JavaScript
  2.         publicvoid SendText(string message)
  3.         {
  4.             MessageBox.Show(message);
  5.         }

Step 8: Ctrl + F5 and this will open the experimental instance of Visual Studio. Create a  Web Application Project in your experimental instance and invoke Browse with multiple browsers. Now each of these will pop up a VS Message box as shown below.

image

So that was a quick introduction to the new Browser Link feature in RC.

You can look at Mad’s Web essentials for Visual Studio 2013 (source) for some cool Browser Link Extensions. Stay tuned for more posts around knowing your Browser Link APIs.

Thanks,

Reshmi Mangalore

Creating New Windows Azure Web Site from Visual Studio 2013 RC

$
0
0

We are now making it easier to create a new Windows Azure Web Site from Visual Studio 2013 RC. This feature can be accessed from the Web Sites sub node under the Windows Azure node in Server Explorer. You would need to install Azure SDK 2.1 before you can use this feature. You can follow these steps to create a new Windows Azure Web Site.

1. Import your Windows Azure subscription. You can do this by right-clicking on the Windows Azure top node in Server Explorer, then select Import Subscriptions…. Find your Windows Azure subscription file and click Import. If you don’t have your subscription file yet, look at the blog in http://blogs.msdn.com/b/avkashchauhan/archive/2012/05/10/downloading-windows-azure-publish-settings-subscription-configuration-file.aspx to download it.

image

2. Once you have your subscription imported, if you already have web sites in Windows Azure, they should show up under the Web Sites node. To create a new Windows Azure Web Site, right click on the Web Sites node, then select Add New Site…

image

3. The “Create site on Windows Azure” dialog box will appear. You can create a new web site without a database, or a new web site with a new database on an existing database server, or a new web site with a new database on a new database server. Fill in all the required information and voila… your new Windows Azure Web Site is ready and you can deploy your web site project there.

image

This feature can also be accessed from the Publish dialog box. To do this, follow these steps.

1. From an existing or a new web project, right click on the project and select Publish…

image

2. In the Publish dialog box, click Import….

3. Select “Import from a Windows Azure web site”

4. If you don’t have your Windows Azure subscription imported to Visual Studio yet, click on the “Add Windows Azure subscription” link and follow the instructions.

5. Once you have your subscription imported, click the New… button. The same “Create site on Windows Azure” dialog box will appear. Once the new site is created, the new site will be selected. Click OK and it will download the publish profile for you.

image

Visual Studio 2013 Custom Web Servers and OwinHost.exe

$
0
0

When running Web applications from within Visual Studio, there have generally been two primary hosts available while developing: a local “development” Web server, or a full version of Internet Information Services (IIS). There has also been a “custom server” option, where a path to a server executable could be entered; however, this was not a widely used option given that most Web applications were built for the ASP.NET pipeline running in some flavor of IIS anyway.

With Visual Studio 2013, ASP.NET will include a new way to compose and host Web applications. In this new model, ASP.NET will shift from a monolithic framework to a set of smaller components put together into a pipeline and hosted in any number of user-selected hosting options. Modularity and flexibility is made possible because all application and hosting components are built on the same core abstraction: OWIN. For more information on OWIN, and the Microsoft OWIN components (known as the “Katana” project), see An Overview of OWIN and Project Katana.

One of the components included in the Microsoft OWIN components is the lightweight, console-based OwinHost.exe. This host finds the user’s startup code and uses it to build an OWIN pipeline; it then uses an HttpListener-based server to receive requests and push them through the OWIN pipeline. OwinHost is a nice, lightweight option for development-time hosting – particularly if the application will ultimately be deployed into a self-hosted environment. And as such, we wanted to improve the experience for connecting it to the Visual Studio experience.

In order to accommodate OwinHost, as well as any additional new hosting frameworks, we made some changes to the way that Web project properties are presented in Visual Studio, and how users select development servers. The new layout shows a drop down for available servers and a property pane which refreshes when a different installed server is selected. By default we continue to include IIS, IIS Express, and External Host (was Custom Server in Visual Studio 2012).

In order to add new servers to the list, we also created an extensible API which users can call either programmatically or via PowerShell. For example, the following code manipulates the custom server API using PowerShell script.

  1. PM> $serverProvider = $dte.GetObject("CustomWebServerProvider")
  2. //This gets the custom server object for all of Visual Studio
  3. PM> $servers = $serverProvider.GetCustomServers("WebApplication2")
  4. //This gets the custom server list for the passed in project (WebApplication2 in this sample)
  5. PM> $servers.AddWebServer('foo', 'c:\test\foo.exe', '/{url}', [System.Management.Automation.Language.NullString]::Value, '{solutiondir}')
  6. //This adds a Custom Server with
  7. //Name: FOO
  8. //Location of EXE to Execute and pass parameters into: C:\Test\foo.exe
  9. //Command Line Arugement: /{URL}
  10. //URL: Not specified (due to the [System.Management.Automation.Language.NullString]::VALUE
  11. //And a Working Directory: {SolutionDir}
  12. //Use of the {URL} and {SolutionDir} means that this server will defer to Visual studio to set those values automatically

Because of the scriptable API, the OwinHost NuGet package can now include a small install.ps1 PowerShell file which registers OwinHost.exe as an available custom server on package installation.

One thing to be aware of is that because of the manner in which the tooling interacts with the underlying project file, a Visual Studio 2013 project which has the OwinHost server registered as a custom server cannot be opened in earlier versions of Visual Studio. This warning is presented before the custom server is registered and it provides an opportunity to cancel the operation.

clip_image002

After installing the OwinHost package, simply open the Web project properties and notice that OwinHost is now a selectable option in the servers dropdown.

clip_image004

Selecting OwinHost reveals several additional configuration options, which can be helpful for tasks such as changing the default port or replacing any of the default infrastructure components (including the server component itself).

As lightweight Web frameworks and hosts become more popular, and as the number of choices continues to grow, we will ensure that the Visual Studio experience remains first class regardless of your chosen component set. So take a look at this new feature, let us know what you think, and let us know how we can continue to improve it and the Visual Studio Web development experience going forward!

- Howard Dierking and Joost de Nijs

Scaffolding asynchronous MVC and Web API controllers for Entity Framework 6

$
0
0

Brief

Entity Framework 6 introduces support for the .NET 4.5 asynchronous programming pattern using the async and await keywords. And in Visual Studio 2013 RC we’re making it easier for you to take advantage of this new capability by optionally generating asynchronous code when you scaffold MVC and Web API controllers.

Why

First thing first. Why would you build an asynchronous controller? Well, asynchronous programming is an important part of building scalable, robust, and responsive web applications.

A web server has a limited number of threads available, and in high load situation all of the available threads might be in use. When that happens, the server can’t process new requests until the threads are freed up. With synchronous code, many threads may be tied up while they aren’t actually doing any work because they’re waiting for I/O to complete. With asynchronous code, when a process is waiting for I/O to complete, its thread is freed up for the server to use for processing other requests. As a result asynchronous code enables server resources to be used more efficiently, and the server is enabled to handle more traffic without delays.

For more information about asynchronous programming, see the tutorial Using Asynchronous Methods in ASP.NET MVC 4[ii] and the video How to Build ASP./NET Web Application Using Async[iii].

How

The MVC and Web API controller scaffolders have a new Use async controller actions check box.
The selection will be remembered next time you use the scaffolder.

MVC Controller using Entity Framework


 

Web API 2 Controller / OData Controller using Entity Framework


What

Following is the sample code generated by the scaffolders. The scaffolders generate code to read, create, update and delete data, using the Entity Framework data context.

Read

When you select the async option, the method is marked as “async”, the EF async API is called, and the “await” keyword is used when calling the EF API.

Create

Update

Delete

 


Understanding Security Features in the SPA Template for VS2013 RC

$
0
0

The blog is based on Visual Studio 2013 RC release.

We have completely rewritten the SPA template from the previous version( MVC 4). Here are some of the changes we made:

  • The authentication story has completely changed. Instead of using cookie (which was used in the last release), we are using OAuth with a bearer token and OWIN, which is more correct in Web API world.
  • A real single page app. We converted all the app pages into one web page and control the visibility of them by knockout.
  • Account controller are now pure Web API controller
  • Removed the todo samples and made the template generate boilerplate code.
  • Updated to bootstrap to modernize and simplify the CSS story.
  • Updated to the new Identity API.
  • We use attribute routes as default route scenario.

Note that SPA VB template is still not available in this RC release. We will ship it with RTM release.

In this blog, I will focus on the security features in SPA template.

  • Bearer token authentication with Web API.
  • How the bearer token is created:

Bearer Token Authentication with Web API

This is one of the most asked for features in Web API. In the SPA template, we implemented this feature with OWIN security middleware. In order to use OWIN bearer token middleware, you need to make sure this package is installed:

  • Microsoft.Owin.Security.OAuth

Here is the code to enable Bearer Token middleware:

Code Snippet
  1. static Startup()
  2. {
  3.     OAuthOptions = new OAuthAuthorizationServerOptions
  4.     {
  5.         TokenEndpointPath = "/Token",
  6.         AuthorizeEndpointPath = "/api/Account/ExternalLogin",
  7.         Provider = new ApplicationOAuthProvider(PublicClientId, IdentityManagerFactory, CookieOptions)
  8.     };
  9. }
  10.  
  11. // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
  12. publicvoid ConfigureAuth(IAppBuilder app)
  13. {
  14.     // Enable the application to use bearer tokens to authenticate users
  15.     app.UseOAuthBearerTokens(OAuthOptions, ExternalOAuthAuthenticationType);
  16. }

The UseOAuthBearerTokens extension method actually enables 3 OWIN middleware components:

  1. Authorization Server middleware.
  2. Application bearer token middleware.
  3. External bearer token middleware.

Here is the pseudo-code for the extension method:

Code Snippet
  1. publicstaticvoid UseOAuthBearerTokens(this IAppBuilder app, OAuthAuthorizationServerOptions options, string externalAuthenticationType)
  2. {
  3.     app.UseOAuthAuthorizationServer(options);
  4.     app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
  5.     {
  6.         AccessTokenFormat = options.AccessTokenFormat,
  7.         AccessTokenProvider = options.AccessTokenProvider,
  8.         AuthenticationMode = options.AuthenticationMode,
  9.         AuthenticationType = options.AuthenticationType,
  10.         Description = options.Description,
  11.         Provider = new AppBuilderExtensions.ApplicationOAuthBearerProvider(),
  12.         SystemClock = options.SystemClock
  13.     });
  14.     app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
  15.     {
  16.         AccessTokenFormat = options.AccessTokenFormat,
  17.         AccessTokenProvider = options.AccessTokenProvider,
  18.         AuthenticationMode = AuthenticationMode.Passive,
  19.         AuthenticationType = externalAuthenticationType,
  20.         Description = options.Description,
  21.         Provider = new AppBuilderExtensions.ExternalOAuthBearerProvider(),
  22.         SystemClock = options.SystemClock
  23.     });
  24. }
   

Authorization server will be responsible to create the bearer token and external bearer token is only used with external logins (Such as Facebook, Google, etc). I will explain them later in the subsequent sections.

After enabling bearer token authentication in active mode, OWIN middleware will authenticate every request with the “Authorization: Bearer” header.  By default, the application bearer token middleware is active.

However, there is still a problem with Web API. What happens if your application enables other authentications?  For example, the SPA template enables application cookie middleware as active mode as well in order to enable other scenarios like MVC authentication. So Web API will still be authenticated if the request has session cookie but without a bearer token. That’s probably not what you want as you would be venerable to CSRF attacks for your APIs. Another negative impact is that if request is unauthorized, both middleware components will apply challenges to it. The cookie middleware will alter the 401 response to a 302 to redirect to the login page. That is also not what you want in a Web API request.

The SPA template demonstrates how to solve this problem in Web API layer. Here is the code snippet from WebApiConfig.Register method:

Code Snippet
  1. // Web API configuration and services
  2. // Configure Web API to use only bearer token authentication.
  3. config.SuppressDefaultHostAuthentication();
  4. config.Filters.Add(newHostAuthenticationFilter(Startup.OAuthOptions.AuthenticationType));

 

SuppressDefaultHostAuthentication will register a message handler and set current principal to anonymous, so no host principal will get passed to Web API. It will also suppress default challenges from OWIN middleware.

HostAuthenticationFilter behavior is the opposite. It will set the principal from specified OWIN authentication middleware. In this case, it is the bearer token middleware, it will also send a challenge to specified middleware when it sees a 401 response. Since this authentication filter is set as global filter, it will apply to all Web APIs. So the result is that Web API will only see the authentication principal from the bearer token middleware and any 401 response from Web API will add a bearer challenge.

Note: the authentication filter is a new filter type in Web API v2. It happens after the message handler but before the AuthorizationAttribute filter. It makes it possible to let you specify different authentication methods at the action level.

After configuring the OWIN bearer token middleware and Web API host authentication settings, you can easily protect your Web API resources with the AuthorizeAttribute.

Your next question is probably how the bearer token is created in the SPA template. In order to conform with OAuth 2.0 spec, we try to use the OWIN Authorization server to create and send bearer tokens to the client in every scenario.  We plan to have a blog post for OWIN Authorization server to explain how it supports all OAuth 2.0 flows. Here I will only explain the authentication flows that are used in SPA template: Resource Owner Password Credentials Grant and Implicit Grant.

Password Login Flow

This flow happens when the user logs in by typing her user name and password in login form ( This is the most common authentication scenario).

In the SPA template, we use OAuth 2.0’s Resource Owner Password Credentials Grant flow for this scenario and implement it in the OWIN Authorization server.

In this flow, the browser sends a POST request with grant type, user name and password and server returns back an access token. For example, the browser sends:

POST http://localhost:47948/Token HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 46
Host: localhost:47948

grant_type=password&username=a&password=aaaaaa

The server responds:

HTTP/1.1 200 OK
Content-Length: 671
Content-Type: application/json;charset=UTF-8
Set-Cookie: .AspNet.Cookies=Ud0iQNZazLq-K8C; path=/; HttpOnly

{
"access_token":"YPo047a0sqJUmle6tkeKmIaRUS",
"token_type":"bearer",
"expires_in":1200,
"userName":"a",
".issued":"Thu, 19 Sep 2013 05:56:32 GMT",
".expires":"Thu, 19 Sep 2013 06:16:32 GMT"
}

In order to support the above password login flow, the  SPA template calls ApplicationOAuthProvider and exposes the token endpoint as “/Token”. (See OAuthAuthorizationServerOptions in the Startup.Auth.cs file).

Code Snippet
  1. publicoverrideasyncTask GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
  2. {
  3.     using (IdentityManager identityManager = _identityManagerFactory.CreateStoreManager())
  4.     {
  5.         if (!await identityManager.Passwords.CheckPasswordAsync(context.UserName, context.Password))
  6.         {
  7.             context.SetError("invalid_grant", "The user name or password is incorrect.");
  8.             return;
  9.         }
  10.  
  11.         string userId = await identityManager.Logins.GetUserIdForLocalLoginAsync(context.UserName);
  12.         IEnumerable<Claim> claims = await GetClaimsAsync(identityManager, userId);
  13.         ClaimsIdentity oAuthIdentity = CreateIdentity(identityManager, claims,
  14.             context.Options.AuthenticationType);
  15.         ClaimsIdentity cookiesIdentity = CreateIdentity(identityManager, claims,
  16.             _cookieOptions.AuthenticationType);
  17.         AuthenticationProperties properties = await CreatePropertiesAsync(identityManager, userId);
  18.         AuthenticationTicket ticket = newAuthenticationTicket(oAuthIdentity, properties);
  19.         context.Validated(ticket);
  20.         context.Request.Context.Authentication.SignIn(cookiesIdentity);
  21.     }
  22. }

What the code above does is quite straightforward:

  1. Checks the password with the Identity API .
  2. Create a user identity for the bearer token.
  3. Creates a user identity for the cookie.
  4. Calls the context.Validated(ticket) to tell the OAuthZ server to protect the ticket as an access token and send it out in JSON payload.
  5. Signs the cookie identity so it can send the authentication cookie.

 

External login flow (Microsoft, Facebook, Twitter and Google)

This flow is a little bit complicated compared with password flow.  The SPA template uses OAuth 2.0 implicit flow to convert an external sign in cookie to an access token and send it back to the browser by URL fragment. Here is a simplified flow diagram for a Facebook login:

image

  1. The User clicks the Facebook Login button and it will trigger a browser redirect to the authorization endpoint with a parameter response_type as token and redirect_uri as application URL. For example: http://localhost:47948/api/Account/ExternalLogin?provider=Facebook&response_type=token&client_id=self&redirect_uri=%2F&state=E2VRvHyopw%2BdYR5uKHbHAyYFmK06Pd%2Fw5LRWO243Tdk%3D
  2. The application knows that user wants to login as Facebook so it sends a challenge to the Facebook authentication middleware to modify the response as 302 and redirect browser to facebook.com. To enable an external login service, see Create an ASP.NET MVC 5 App with Facebook and Google OAuth2 and OpenID Sign-on or  External Authentication Service.
  3. The user signs in with her facebook account and which grants access to this application.
  4. Facebook sends a HTTP 302 back and redirects the browser back to Facebook callback URL on server, by default it’s “/signin-facebook”. You can change it with Facebook authentication options.
  5. The Facebook authentication middleware asks for access token and user data from facebook.com.
  6. The Facebook authentication middleware redirects the browser back to the authorization endpoint and converts the facebook data into claims and sets external sign in cookie.
  7. The user agents redirects to the authorization endpoint with the external cookie in the request.
  8. The authorization endpoint checks the external sign in cookie principal and finds the associated application user, then signs in the user as Bearer authentication type into the authorization server middleware. Since the authorization server sees that the request parameter response_type is token (in step 1), it will trigger implicit flow, which will create access the token and append it to the redirect_uri (step 1) as URL fragment. For example:

    HTTP/1.1 302 Found
    Cache-Control: no-cache
    Pragma: no-cache
    Expires: -1
    Location: /#access_token=asd2342SDIUKJdsfjk3234&token_type=bearer&expires_in=1200&state=06hwltIjvnTn44hc
    Set-Cookie: .AspNet.External=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT
    Set-Cookie: .AspNet.Cookies=WJgdyZQs9N8TG20EWnik-j0_; path=/; HttpOnly
    Content-Length: 0

 

The key logic here is in the authorization endpoint, which is “api/Account/ExternalLogin” in the SPA template (See OAuthAuthorizationServerOptions in the Startup.Auth.cs file).

Code Snippet
  1. // GET api/Account/ExternalLogin
  2. [OverrideAuthentication]
  3. [HostAuthentication(Startup.ExternalCookieAuthenticationType)]
  4. [AllowAnonymous]
  5. [HttpGet("ExternalLogin", RouteName = "ExternalLogin")]
  6. publicasyncTask<IHttpActionResult> ExternalLogin(string provider)
  7. {
  8.     if (!User.Identity.IsAuthenticated)
  9.     {
  10.         returnnewChallengeResult(provider, this);
  11.     }
  12.  
  13.     ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity asClaimsIdentity);
  14.  
  15.     if (externalLogin == null)
  16.     {
  17.         return InternalServerError();
  18.     }
  19.  
  20.     string userId = await IdentityManager.Logins.GetUserIdForLoginAsync(externalLogin.LoginProvider,
  21.         externalLogin.ProviderKey);
  22.  
  23.     bool hasRegistered = userId != null;
  24.  
  25.     if (hasRegistered)
  26.     {
  27.         Authentication.SignOut(Startup.ExternalCookieAuthenticationType);
  28.         IEnumerable<Claim> claims = awaitApplicationOAuthProvider.GetClaimsAsync(IdentityManager, userId);
  29.         ClaimsIdentity oAuthIdentity = ApplicationOAuthProvider.CreateIdentity(IdentityManager, claims,
  30.             OAuthOptions.AuthenticationType);
  31.         ClaimsIdentity cookieIdentity = ApplicationOAuthProvider.CreateIdentity(IdentityManager, claims,
  32.             CookieOptions.AuthenticationType);
  33.         AuthenticationProperties properties = awaitApplicationOAuthProvider.CreatePropertiesAsync(
  34.             IdentityManager, userId);
  35.         Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
  36.     }
  37.     else
  38.     {
  39.         IEnumerable<Claim> claims = externalLogin.GetClaims();
  40.         ClaimsIdentity identity = ApplicationOAuthProvider.CreateIdentity(IdentityManager, claims,
  41.             OAuthOptions.AuthenticationType);
  42.         Authentication.SignIn(identity);
  43.     }
  44.  
  45.     return Ok();
  46. }

The OverrideAuthentication attribute is used to suppress global authentication filters. It suppresses the application bearer token host authentication filter in the SPA template.

This action enables ExternalCookieAuthenticationType host authentication, which represents the user’s external sign in state. With this setting, the User.Identity will be set as the external login identity, for example, Facebook identity.

AllowAnonymous enables a user to reach this endpoint without an external sign in state. It will trigger an external sign in challenge when the user is anonymous. That’s the scenario when the unauthorized user clicks the Facebook button to trigger a redirection to facebook.com.

After the browser redirects back from facebook.com and gets the external sign in cookie from the Facebook authentication middleware, this action will check if the external login data has already been associated with existing user.

If it has, it will sign in with both the application bearer token identity and the application cookie identity. As described in the step 8 of external login flow above, it will trigger a redirection and add an access token in URL fragment.

If not, it will sign in with the external bearer token identity and it will also be sent to the client by implicit flow. The client code will check if the user is registered by the code and show up the register external user page as needed. After the user is registered, the client code will trigger the external login flow again to get the application bearer token.

Acknowledgements

I’d like to thank Rick Anderson: (twitter @RickAndMSFT ) for the help on the blog. Rick  is a senior programming writer for Microsoft focusing on Azure and MVC.

 

Thanks,

Hongye Sun (ASP.NET MVC and Web API team)

OWIN Startup Class Detection

$
0
0

OWIN Startup class is the entry point for any OWIN based application. When you use VS 2013 to create web projects, a Startup class is created for you by VS. 

Check out how Katana runtime does the OWIN Startup class detection and learn how you can create an application with multiple Startup configuration classes suitable for different environments. 

High level topics covered:

  • OWIN Startup detection algorithm
  • Visual studio 2013 - OWIN Startup item template
  • Friendly Startup names
  • Startup class using friendly name using web.config & OwinHost.exe command line parameters. 

Organizational Accounts in Visual Studio 2013 RC

$
0
0

Visual Studio 2013 Preview shipped with support to create new ASP.NET projects that can be easily configured with organizational accounts. This support has been simplified and enhanced in this RC version. You can find a detailed step-by-step tutorial on creating an ASP.NET MVC project with single organizational identity at Developing ASP.NET Apps with Windows Azure Active Directory.

The biggest change in this release is the addition of support for configuring ASP.NET WebAPI project with Windows Azure Active Directory identity. For more information on changes done in RC release, you can look at What’s New for Organizational Accounts in Visual Studio 2013 RC

Web Publish how to automate multi-project publish with file system

$
0
0

The other day I received an email from a customer with a question which I’ve summarized as below.

I have a solution containing multiple web projects. One of the projects, _RootSite, is the top level website which I want to publish. It’s an MVC project. I also have other web projects in the same solution. These other projects are apps themselves but being published under _RootSite as an area. In some cases I’d like to publish my entire site, in other cases just the areas. Sometimes when I publish an area I need to refresh the assembly for _RootSite. How can I automate this with the most flexibility?

I am publishing by using file copy over a network share.

To help visualize the issue take a look at the screenshot below which is from the samples that I created to accompany this post (download links at the bottom of the post here).

image

In this case both AdminArea and HrArea will be published to _RootSite\Areas under their own folders.

The way that I’d solve this is to break it down into two steps using MSBuild and PowerShell to automate all steps. The first step is to build and publish all projects to the local file system. You can think of this an “intermediate publish folder”. From there you can construct copy commands to publish each part.

In the samples you’ll find publish.proj. This file is used to build and publish each (or all) components. This file is composed of two sections; a build section and a publish section. The build section takes care of building and publishing to that intermediate publish folder. The publish related targets perform the actual publish operations to prod.

Let’s take a look at the build related elements in that file. In this post I’ll use the publish injection technique which I’ve recently blogged. If you haven’t read that you may want to take a look to fully understand what is happening here.

Build related elements from publish.proj

<PropertyGroup>
  <VisualStudioVersion Condition=" '$(VisualStudioVersion)'=='' ">11.0</VisualStudioVersion>
  <Configuration Condition=" '$(Configuration)'=='' ">Release</Configuration>
  <SourceRoot Condition=" '$(SourceRoot)'=='' ">$(MSBuildThisFileDirectory)..\</SourceRoot>
  <!-- Location for build output of the project -->
  <OutputRoot Condition=" '$(OutputRoot)'=='' ">$(MSBuildThisFileDirectory)..\BuildOutput\</OutputRoot>
  <!-- Root for the publish output -->
  <PublishFolder Condition=" '$(PublishFolder)'==''">C:\temp\Publish\MySite\</PublishFolder>
  <DeployOnBuild Condition=" '$(DeployOnBuild)'=='' ">true</DeployOnBuild>
  <BuildBeforePublish Condition=" '$(BuildBeforePublish)'=='' ">true</BuildBeforePublish>
</PropertyGroup>
  
<ItemGroup>
  <ProjectsToBuild Include="$(SourceRoot)RootSite\_RootSite.csproj">
    <AdditionalProperties>publishUrl=$(PublishFolder);</AdditionalProperties>
  </ProjectsToBuild>

  <ProjectsToBuild Include="$(SourceRoot)AdminArea\AdminArea.csproj">
    <AdditionalProperties>publishUrl=$(PublishFolder)Areas\Admin\;</AdditionalProperties>
  </ProjectsToBuild>

  <ProjectsToBuild Include="$(SourceRoot)HrArea\HrArea.csproj">
    <AdditionalProperties>publishUrl=$(PublishFolder)Areas\HR\;</AdditionalProperties>
  </ProjectsToBuild>
</ItemGroup>

<PropertyGroup>
  <BuildAndPublishDependsOn>
    $(BuildAndPublishDependsOn);
    CoreBuildAndPublish;
    Publish
  </BuildAndPublishDependsOn>
</PropertyGroup>
<Target Name="BuildAndPublish" DependsOnTargets="$(BuildAndPublishDependsOn)" />
  
<Target Name="CoreBuildAndPublish">
  <Message Text="Building and publishing all projects in ProjectsToBuild [@(ProjectsToBuild)]"
            Condition=" '$(DeployOnBuild)'=='true' "/>
  <Message Text="Building all projects in ProjectsToBuild [@(ProjectsToBuild)]"
            Condition=" '$(DeployOnBuild)'!='true' "/>
    
  <MSBuild Projects="@(ProjectsToBuild)"
            Properties="
              VisualStudioVersion=$(VisualStudioVersion);
              Configuration=$(Configuration);
              OutputPath=$(OutputRoot);
              WebPublishMethod=FileSystem;
              DeployOnBuild=$(DeployOnBuild);
              DeployTarget=WebPublish;
              PublishProfile=$(MSBuildThisFileFullPath)" />
</Target>

Here you can see that we have defined the main build related target; BuildAndPublish. This is a publish to the intermediate publish folder. In this snippet I define some MSBuild parameters which are required when building the projects. I define the projects which I want to build in the ProjectsToBuild item list. Along with that I declare all the MSBuild properties which are specific to that project in the AdditionalProperties metadata. FYI for more info on Properties vs. AdditionalProperties take a look at my previous post. In this case the only parameter which varies from project to project is the publishUrl. This defines where the project will be published to.

For the _RootSite project publishUrl is $(PublishFolder), the intermediate publish folder. In my case this is c:\temp\Publish\MySite\. For AdminArea publishUrl is $(PublishFolder)Areas\Admin and similarly for HrArea. This will ensure the contents are published to the correct location.

Inside CoreBuildAndPublish I invoke the MSBuild task to build each project and publish to the local intermediate publish folder.  After invoking that all projects will be built and the $(PublishFolder) will be populated.

Now let’s take a look at the publish related elements in publish.proj.

Publish elements from publish.proj

<PropertyGroup>
  <ProdPublishFolder Condition=" '$(ProdPublishFolder)'=='' ">C:\temp\Publish\MySite-Prod\</ProdPublishFolder>

  <!-- If /p:BuildBeforPublish is true then invoke build before any publish operations. -->
  <PublishComputeItemsDependsOn Condition=" '$(BuildBeforePublish)'=='true' ">$(PublishComputeItemsDependsOn);BuildAndPublish</PublishComputeItemsDependsOn>
    
  <PublishComputeItemsDependsOn>$(PublishComputeItemsDependsOn);</PublishComputeItemsDependsOn>
  <PublishMySiteBinDependsOn>$(PublishMySiteBinDependsOn);PublishComputeItems</PublishMySiteBinDependsOn>
  <PublishMySiteAllDependsOn>$(PublishMySiteAllDependsOn);PublishComputeItems</PublishMySiteAllDependsOn>
  <PublishAdminAreaDependsOn>$(PublishAdminAreaDependsOn);PublishComputeItems</PublishAdminAreaDependsOn>
  <PublishHrAreaDependsOn>$(PublishHrAreaDependsOn);PublishComputeItems</PublishHrAreaDependsOn>  
</PropertyGroup>

  
<!-- 
This target populates the publish items so that they can be
used in the Publish* targets.
-->
<Target Name="PublishComputeItems" DependsOnTargets="$(PublishComputeItemsDependsOn)">
  <ItemGroup>
    <PubMySiteBinFiles Include="$(PublishFolder)bin\**\*"/>

    <PubMySiteAll Include="$(PublishFolder)**\*"/>

    <PubMySiteAdminArea Include="$(PublishFolder)Areas\Admin\**\*"/>
      
    <PubMySiteHrArea Include="$(PublishFolder)Areas\HR\**\*"/>
  </ItemGroup>
</Target>

<!-- This is just a placeholder target so that we can specify /p:PublishTargets from the cmd line -->
<Target Name="Publish" DependsOnTargets="$(PublishTargets.Split('|'))"></Target>
  
<Target Name="PublishMySiteBin" 
        DependsOnTargets="$(PublishMySiteBinDependsOn)"
        Inputs="@(PubMySiteBinFiles)" 
        Outputs="@(PubMySiteBinFiles->'$(ProdPublishFolder)bin\%(RecursiveDir)%(FileName)%(Extension)')">
  <Copy SourceFiles="@(PubMySiteBinFiles)" 
        DestinationFiles="@(PubMySiteBinFiles->'$(ProdPublishFolder)bin\%(RecursiveDir)%(FileName)%(Extension)')"/>
</Target>
  
<Target Name="PublishMySiteAll" 
        DependsOnTargets="$(PublishMySiteAllDependsOn)"
        Inputs="@(PubMySiteAll)"
        Outputs="@(PubMySiteAll->'$(ProdPublishFolder)%(RecursiveDir)%(FileName)%(Extension)')">
  <Copy SourceFiles="@(PubMySiteAll)"
        DestinationFiles="@(PubMySiteAll->'$(ProdPublishFolder)%(RecursiveDir)%(FileName)%(Extension)')"/>
</Target>

<Target Name="PublishAdminArea" 
        DependsOnTargets="$(PublishAdminAreaDependsOn)"
        Inputs="@(PubMySiteAdminArea)"
        Outputs="@(PubMySiteAdminArea->'$(ProdPublishFolder)Areas\Admin\%(RecursiveDir)%(FileName)%(Extension)')">
  <Copy SourceFiles="@(PubMySiteAdminArea)"
        DestinationFiles="@(PubMySiteAdminArea->'$(ProdPublishFolder)Areas\Admin\%(RecursiveDir)%(FileName)%(Extension)')"/>
</Target>
  
<Target Name="PublishHrArea" 
        DependsOnTargets="$(PublishHrAreaDependsOn)"
        Inputs="@(PubMySiteHrArea)"
        Outputs="@(PubMySiteHrArea->'$(ProdPublishFolder)Areas\Hr\%(RecursiveDir)%(FileName)%(Extension)')">
  <Copy SourceFiles="@(PubMySiteHrArea)"
        DestinationFiles="@(PubMySiteHrArea->'$(ProdPublishFolder)Areas\Hr\%(RecursiveDir)%(FileName)%(Extension)')"/>
</Target>

Here we define leaf targets like, PublishMySiteAll, PublishMySiteBin, etc. These targets contain a simple Copy command. All of these targets have Inputs and Outputs so that these are all incremental. Up to date files will be skipped by MSBuild automatically by using Inputs and Outputs. All of these targets depend on the PublishComputeItems target. This target is responsible for populating the item lists used by other publish targets. So if I want to publish the entire site I can execute the PublishMySiteAll target. If I just want to publish the Hr area I can invoke the PublishHrArea target and so forth. Pretty straight forward stuff here.

Now let’s tie it all together with PowerShell.

In the samples you’ll find publish.ps1. This is the file that will be used to simplify the user experience and drive the entire process. The full contents are below.

param(
    [switch]
    $BuildProjects,

    [switch]
    $PublishAll,

    [switch]
    $PublishMySiteBin,

    [switch]
    $PublishAdminArea,

    [switch]
    $PublishHrArea
)

function Get-ScriptDirectory
{
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    $path = Split-Path $Invocation.MyCommand.Path
    return ("{0}\" -f $path)
}

# we need to build the msbuild command
function Get-MSBuildCommandArgs(){
    param(
        [Parameter(Mandatory=$true)]
        [string]
        $logsDir
    )

    $cmdArgs = @()
    $cmdArgs += ("{0}publish.proj" -f $scriptDir)
    $cmdArgs += '/p:Configuration=release'
    $cmdArgs += '/p:VisualStudioVersion=11.0'

    if($BuildProjects){
        $cmdArgs += "/p:BuildBeforePublish=true"
    }
else {
$cmdArgs += "/p:BuildBeforePublish=false"
}
    foreach($target in (Get-PublishTargetsFromParams)){
        $cmdArgs += ("/t:{0}" -f $target)
    }

    $logFileBaseName = ("publish-$(get-date -f yyyy.MM.dd.ss.ff)")

    # add logging parameters here
    # /flp1:"v=d;logfile=logs\%~n0.d.log" /flp2:"v=diag;logfile=logs\%~n0.diag.log"
    $cmdArgs += ('/flp1:"v=d;logfile={0}{1}.d.log" ' -f $logsDir, $logFileBaseName)
    $cmdArgs += ('/flp2:"v=diag;logfile={0}{1}.diag.log" ' -f $logsDir, $logFileBaseName)

    return $cmdArgs
}

function Get-PublishTargetsFromParams(){
    $pubTargets = @()
        
    if($PublishAll){
        # if PublishAll is passed we do not need to add any additional targets
        # for any other publish targets
        $pubTargets += "PublishMySiteAll"
    }
    else{
        if($PublishMySiteBin){
            $pubTargets += "PublishMySiteBin"
        }
        if($PublishAdminArea){
            $pubTargets += "PublishAdminArea"
        }
        if($PublishHrArea){
            $pubTargets += "PublishHrArea"
        }
    }

    return $pubTargets
}
function Get-MSBuildPath(){
    return "$env:windir\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe"
}

# begin script

$scriptDir = (Get-ScriptDirectory)
$logsDir = (Join-Path -Path $scriptDir -ChildPath "logs\")
if(!(Test-Path $logsDir)){
    mkdir $logsDir
}
$msbuildCmd = (Get-MSBuildPath)
$allArgs  = (Get-MSBuildCommandArgs -logsDir $logsDir)
"Calling msbuild.exe with the following parameters. [$msbuildCmd] [$allArgs] " | Write-Host
& $msbuildCmd $allArgs

 

This script will build up the msbuild command based on the switches above and then invoke the correct targets based on the inputs. This is pretty straight forward PowerShell as well. It just interprets the switches that are passed in and builds the correct set of properties/targets to be passed to msbuild.exe.

.\publish.ps1 -BuildProjects -PublishAll

This will build all projects and publish them.

.\publish.ps1 -BuildProjects -PublishHrArea

This will build all projects and only publish the HR area

.\publish.ps1 -BuildProjects -PublishAdminArea -PublishMySiteBin

This will build all projects and publish the bin\ folder of MySite as well as the Admin area

.\publish.ps1 -PublishAdminArea -PublishMySiteBin

This will skip the build and pub to intermediate publish folder (must have been performed earlier at some point) and publish the Admin area and the bin\ folder of MySite.

 

You can find all the samples at https://dl.dropboxusercontent.com/u/40134810/blog/SubappPublish.zip. You can find the latest version in my publish-samples repository at SubappPublish.

If you have any comments on this please let us know by replying below.

 

Sayed Ibrahim Hashimi | http://msbuildbook.com | @SayedIHashimi

Attribute Routing changes for ASP.NET Web Stack shipped in VS2013 RC

$
0
0

For the VS2013 Preview release, we published two articles about Attribute Routing for Web API 2:

· http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

· http://www.asp.net/web-api/overview/web-api-routing-and-actions/create-a-rest-api-with-attribute-routing

The VS2013 RC release includes more changes and features for attribute routing:

1. Explicitly declare a route template on an action

In RC, if attribute routing is enabled, you must explicitly declare the attribute for the desired actions. In Preview, you don’t have to.

clip_image001

2. Added support for overriding RoutePrefix attribute.

In the following controller code, the action to ‘get all the books’ has a route template like “~/”. This overrides the RoutePrefix for this action and a user can reach this action by requesting GET on http://hostname:hostport/ .

clip_image002

3. Support for multiple RoutePrefix attributes on a controller has been removed. Only one RoutePrefix attribute can be applied to a controller.

4. The Order property is removed from the RoutePrefix attribute.

We’ll be changing even more for RTM -- stay tuned. For information about what’s planned, see the attribute routing design specification on the CodePlex site.

Viewing all 7144 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>