Scott Hanselman

ASP.NET 5 (vNext) Work in Progress - Exploring TagHelpers

November 20, '14 Comments [103] Posted in ASP.NET | ASP.NET MVC
Sponsored By

TagHelpers are a new feature of ASP.NET 5 (formerly and colloquially ASP.NET vNext) but it's taken me (and others) some time to fully digest them and what they mean.

Note that this, and all of ASP.NET 5 is a work in progress. TagHelpers can and will change. There is NO tooling support in Visual Studio for them, as they are changing day to day, so just be aware. That's why this post (and series is called Work in Progress.)

Historically we've used HtmlHelpers within a Razor View, so when you wanted a Label or a TextBox you'd do this. This is from the ASP.NET 5 Starter Web example.

<li>@Html.ActionLink("Home", "Index", "Home")</li>

There you have some HTML, then we start some C# with @ and then switch out. It's inline C#, calling a function that will return HTML.

Here's the same thing, using a TagHelper.

<li><a controller="Home" action="Index">Home</a></li>

The source for TagHelpers is (as with all ASP.NET source) up on GitHub, here. This is an anchor, A, so it'll be in AnchorTagHelper. The code is very simple, in fact, gets a collection of attributes and decides which to act upon.

In this case, "controller" and "action" are not HTML5 attributes, but rather ones that ASP.NET is looking for.

Question for You - Would you rather have these attributes and ones like them (including your own) be prefixed? Perhaps asp:controller or asp-controller? That's an open issue you can comment on! You could do [HtmlAttributeName("asp:whatever")] on a property or [TagName("foo")] for a tag if you liked.

How do these attributes get mapped to a TagHelper? Well, an attribute name is mapped directly to a C# property and automatically injected. See how AnchorTagHelper has public properties Action and Controller?

It's important to note that this isn't the second coming of WebForms controls, while the possible asp:foo syntax may look familiar (even though a prefix is optional.) This is more like syntactic sugar that gives you a compact way to express your intent. It doesn't give you any "control lifecycle" or anything like that.

Personally, I'd love to see them look different in the editor. For example, rather than

Tag Helpers

I'd like to see italics, or maybe a desaturation to show what's server-side and what's not, which will be super important if I'm NOT using a prefix to distinguish my attributes.

Tag Helpers, desaturated

The code below in this Before and After results in the same HTML and the same behavior. A nice aspect of TagHelpers it that you avoid the context switch from markup to C#.

Here is another example, a login partial form, before...

@using System.Security.Principal

@if (User.Identity.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
{
@Html.AntiForgeryToken()
<ul class="nav navbar-nav navbar-right">
<li>
@Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Manage", "Account", routeValues: null, htmlAttributes: new { title = "Manage" })
</li>
<li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
</ul>
}
}
else
{
<ul class="nav navbar-nav navbar-right">
<li>@Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
<li>@Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}

and after...with the Microsoft.AspNet.Mvc.TagHelpers package added in project.json and then @addtaghelper "MyAssemblyName" in either your ViewStart.cshtml to get this in all views, or separately within a single view page.

@using System.Security.Principal

@if (User.Identity.IsAuthenticated)
{
<form method="post" controller="Account" action="LogOff" id="logoutForm" class="navbar-right">
<ul class="nav navbar-nav navbar-right">
<li>
<a controller="Account" action="Manage" title="Manage">Hello @User.Identity.GetUserName()!</a>
</li>
<li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
</ul>
</form>
}
else
{
<ul class="nav navbar-nav navbar-right">
<li><a id="registerLink" controller="Account" action="Register">Register</a></li>
<li><a id="loginLink" controller="Account" action="Login">Log in</a></li>
</ul>
}

This makes for much cleaner markup-focused Views. Note that this Sample is a spike that Damian Edwards has on his GitHub, but you have TagHelpers in the Beta 1 build included with Visual Studio 2015 preview or OmniSharp. Get involved!

Remember also to check out http://www.asp.net/vnext and subscribe to my YouTube Channel and this playlist of the ASP.NET Weekly Community Standup. In this episode we talked about TagHelpers in depth!

Related Posts

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

Announcing .NET 2015 - .NET as Open Source, .NET on Mac and Linux, and Visual Studio Community

November 12, '14 Comments [180] Posted in ASP.NET | ASP.NET MVC | Open Source | VS2015
Sponsored By

It's happening. It's the reason that a lot of us came to work for Microsoft, and I think it's both the end of an era but also the beginning of amazing things to come.

The .NET 2015 wave of releases is upon us. Here's what's happening and we announced it today in New York. There's a lot here, so drink it all in slowly.

Be sure to check out all the blog posts I'm linking to at the end, but here's my personal rollup and take on the situation.

  • We are serious about open source and cross platform.
    • .NET Core 5 is the modern, componentized framework that ships via NuGet. That means you can ship a private version of the .NET Core Framework with your app. Other apps' versions can't change your app's behavior.
    • We are building a .NET Core CLR for Windows, Mac and Linux and it will be both open source and it will be supported by Microsoft. It'll all happen at https://github.com/dotnet.
    • We are open sourcing the RyuJit and the .NET GC and making them both cross-platform.
  • ASP.NET 5 will work everywhere.
    • ASP.NET 5 will be available for Windows, Mac, and Linux. Mac and Linux support will come soon and it's all going to happen in the open on GitHub at https://github.com/aspnet.
    • ASP.NET 5 will include a web server for Mac and Linux called kestrel built on libuv. It's similar to the one that comes with node, and you could front it with Nginx for production, for example.
  • Developers should have a great experience.
    • There is a new FREE SKU for Visual Studio for open source developers and students called Visual Studio Community. It supports extensions and lots more all in one download. This is not Express. This is basically Pro.
    • Visual Studio 2015 and ASP.NET 5 will support gulp, grunt, bower and npm for front end developers.
    • A community team (including myself and Sayed from the ASP.NET and web tools team) have created the OmniSharp organization along with the Kulture build system as a way to bring real Intellisense to Sublime, Atom, Brackets, Vim, and Emacs on Windows, Linux, and Mac. Check out http://www.omnisharp.net as well as blog posts by team members Jonathan Channon
  • Even more open source.
    • Much of the .NET Core Framework 4.6 and its Reference Source source is going on GitHub. It's being relicensed under the MIT license, so Mono (and you!) can use that source code in their .NET implementations.
    • There's a new hub for Microsoft open source that is hosted GitHub at http://microsoft.github.io.

Open sourcing .NET makes good sense. It makes good business sense, good community sense, and today everyone at Microsoft see this like we do.

Open .NET

Related Links


Sponsor: Big thanks to Aspose for sponsoring the feed this week! Working with Files? Aspose.Total for .NET has all the APIs you need to create, manipulate and convert Microsoft Office documents and many other formats in your applications. Start a free trial today.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

NuGet Package of the Week - Courtesy Flush to flush buffers earlier and optimize time to first byte

November 6, '14 Comments [25] Posted in ASP.NET | ASP.NET MVC | NuGet | NuGetPOW
Sponsored By

Yes, really. It's got to be the best name for an open source library out there. It's a great double entendre and a great name for this useful little library. Perhaps English isn't your first language, so I'll just say that a courtesy flush gives the next person a fresh bowl. ;)

However, in the computer world "flushing a buffer" means forcing a buffer to be moved along, usually to a file or the network. Rather than holding data, you flush it, and move it along.

Nik from Glimpse has a small NuGet package called Courtesy Flush. He's got a good write-up on his blog.

image

It's a library to enable easier flushing of your buffer in ASP.NET MVC. From their site:

Why Flush Early?

Flushing early can provide performance improvements in web applications and has been a recomended best practice in the web performance community since 2007.

To find out more, check out Nik's blog where he covered the benefits of flushing early in two posts:

It builds on top of ASP.NET ActionFilters, which you can apply as attributes to your methods, or call within controllers.

Let's say that you have some server-side work that's very slow. That slow operation could hold up the rendering of your page until it completes. With a pre-flush like this you can get bytes onto the network and into the user's browser faster.

Here we render some information and get it out fast before we do something that's unavoidably slow.

public ActionResult About()
{
ViewBag.Title = DateTime.Now.Second;
this.FlushHead();

Thread.Sleep(2000);
ViewBag.Message = "Your application description page.";

return View();
}

Let's think about really specifically. It's important to know WHY you would want to do this and what exactly happens in the browser.

If you have a long running, but important process (we are pretending that Thread.Sleep(2000) is important) that takes 2 seconds, no HTML is sent to the browser. It's just waiting. The timeline looks like this:

Here we didn't flush

See that blue line? We waited almost 5 seconds for the /about page, and while we were waiting, no Javascript and no CSS were being loaded. Why not? How could the browser know if it isn't seen the <head> of your HTML?

For an optimization, we could FLUSH the buffers that we have up to this point, putting the HTML that we have so far onto the network.

The Layout.cshtml we have a call to @Html.FlushHead() to get the the _Head.cshtml out and into the hands of the browser. It might look like this:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@if (ViewBag.Description != null)
{
<meta name="description" content="@ViewBag.Description">
}
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>

Here's what the SAME page looks like with the <head> flushed out first.

Here we flushed

Look closely at the timeline. Here, I'll do it for you...below shows when we flushed early versus just waiting.

See how when we flushed the head it gave the browser enough information to stat loading some css and javascript we had in the <head?> The whole page took 5 seconds, but when we flush at least we get things going early, while when we don't flush we can't do a thing until the long running task finishes.

See the difference?

See the difference? Now, to be clear, don't blindly go and add optimizations without reading the code and understanding what's going on, but this is a nice tool for our ASP.NET toolbox.

We may see a similar but even more powerful technique in ASP.NET vNext that includes async flushes at multiple points, while updating the model as data is available.


Sponsor: Big thanks to Aspose for sponsoring the feed this week! Working with Files? Aspose.Total for .NET has all the APIs you need to create, manipulate and convert Microsoft Office documents and many other formats in your applications. Start a free trial today.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

Introducing ASP.NET vNext

May 12, '14 Comments [147] Posted in ASP.NET | ASP.NET MVC | ASP.NET Web API | Open Source
Sponsored By

There’s some really cool stuff going on on the ASP.NET and Web Tools team. The team has been pushing open stuff at Microsoft for a few years now and we've joined forces with the amazing innovators from the .NET core team and beyond! Some of these features are 10+ years in the making from a host of technical wizards across many teams and disciplines.

Today we’re announcing a preview (read: alpha) of the next generation of .NET on the Server.

You may have heard about some of these announcements at Build:

ASP.NET vNext will take things to the next level. Today, you run ASP.NET using the same CLR that desktop apps use. We’re adding a cloud-optimized (my cloud, your cloud, their cloud - server stuff) version optimized for server scenarios like low-memory and high-throughput.

ASP.NET vNext will let you deploy your own version of the .NET Framework on an app-by-app-basis. One app with new libraries can’t break an app next door with a different version. Different apps can even have their own cloud-optimized CLR of their own version. The CLR and cloud-optimized libraries are NuGet packages!

In this screenshot you can see build 418 and build 420 of the new framework (note how small they are) in my packages folder. These NuGet packages include the complete "Core CLR" and the cloud-optimized .NET Framework. You can deploy your own CLR and .NET Framework with your app as a NuGet.

Holy crap it's ASP.NET vNext

I can run ASP.NET vNext apps within Visual Studio, of course, and within IIS, but I can also easily "self-host" them from the command line or within my own application. This alpha includes command line tools for running and managing ASP.NET vNext apps.

The "kvm" command allows me to control my environment. I run "kvm list" to see what versions of the ASP.NET vNext are available. I can switch between them on a per-environment basis:

C:\>kvm list

Active Version Runtime Architecture Location
------ ------- ------- ------------ --------
0.1-alpha-build-0418 svr50 x86 C:\Users\scottha\.kre\packages
* 0.1-alpha-build-0418 svrc50 x86 C:\Users\scottha\.kre\packages
0.1-alpha-build-0420 svr50 x86 C:\Users\scottha\.kre\packages
0.1-alpha-build-0420 svrc50 x86 C:\Users\scottha\.kre\packages

I set the active version with "kvm use version" and opened two command prompts, setting different CLR and .NET versions in each.

I’m running the same app twice, once per command prompt. I put version 420 on port 5420 and version 418 on port 5418.

Two Command Prompts two .NET Frameworks

This little app below outputs the current running version of ASP.NET vNext. Here I’m running the same app at the same time under different builds of the next generation of ASP.NET

Two URLs two .NET Frameworks

The project system is also changing - we’re integrating packages.config, NuGet specifications (nuspec), and project files (csprojs) into a unified view of your project dependencies expressed in a project.json file.

NuGet packages and class libraries are treated the same. You get full intellisense in the project.json file and NuGet packages come down automatically and transparently. Even better, let’s say NuGet package Foo.Bar has a bug but you’ve only got the NuGet package. You can make a folder called Foo.Bar in our local project and put the source via "git clone" in that folder. This is great for open source projects. That local version overrides the NuGet, allowing you to easily patch bugs locally in libraries while you wait for a new release. When a new fixed NuGet-distributed version shows up, update the version and delete the local source.

New project system

One of the great aspects of environments like node or rails is that they are "no compile." Just change some code and hit refresh. With the next version of ASP.NET you get the power and throughput of the .NET runtime plus the "Roslyn" compiler-as-a-service for a "no-compile compile." That means means during development time you can just change your C# classes and hit Refresh in the browser. It's the power of .NET with the dynamism of a refresh-and-go development experience.

NOTE: This isn't ASP.NET Websites, or Razor View compilation - this is the whole thing, compiled in memory. You can use Visual Studio for development, or text editors like Sublime, or freakin' Notepad. (Of course, if you want assemblies on disk, you can do that too.)

See my web app’s bin folder in the screenshot below? There’s no assemblies in there because the assemblies never exist on the disk. It’s actually faster and easier to have the compiler do all the work in memory. This way you don’t have to read source, write out dlls, then read the dlls in again. (That DLL is part of the magic that makes it all happen.)

No binaries on disk!

If you like, when your web projects build for deployment, they can also build as NuGet packages. You publish your project and every needed dependency comes along.

You’ll be able to put ASP.NET vNext on your existing servers, any hoster, and Azure of course.

You can opt in or out of the cloud optimized framework for compatibility. The next version of ASP.NET is modular and all about choice. your choice of framework, your choice of runtime, your choice of operating system, your choice of text editor.

ASP.NET vNext is:

  • Cloud and server-optimized
  • ASP.NET MVC and Web API have been unified into a single programming model
  • No-compile developer experience
  • Dependency injection out of the box
  • Side by side - deploy the runtime and framework with your application
  • NuGet everything - even the runtime itself
  • All Open Source via the .NET Foundation and takes contributions

Oh, and by the way

  • ASP.NET vNext (and Rosyln) runs on Mono, on both Mac and Linux today. While Mono isn't a project from Microsoft, we'll collaborate with the Mono team, plus Mono will be added to our test matrix. It's our aspiration that it "just work."
ASP.NET on a Mac

There will be lots of new information and details coming out over the next several months!


Sponsor: Many thanks to Izenda for sponsoring the blog feed this week! Intuitive Ad Hoc Reporting with Stunning Visualizations - Embed real time dashboards into your ASP.NET applications for easy, custom reports across all devices. Download a FREE TRIAL of Izenda Today!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web

Adding Two-Factor authentication to an ASP.NET application

April 8, '14 Comments [30] Posted in ASP.NET | ASP.NET MVC
Sponsored By
German Lorenz cipher machine by Timitrius used under CC Attributin

ASP.NET Identity 2.0 was released last month and it's got a number of significant updates and new features that are worth checking out. For historical context, read the "Introduction to ASP.NET Identity" article that includes a lot of background and information on why certain decisions were made, as well as an  overview of some of the goals of ASP.NET Identity 2.0 like:

  • One Identity system for ASP.NET Web Forms, MVC, Web API, and Web Pages
  • Total control over user profile schema.
  • Pluggable storage mechanisms from Windows Azure Storage Table Service to NoSQL databases
  • Unit Testable
  • Claims-based Auth adds more choice over simple role membership
  • Social Logins (MSFT, FB, Google, Twitter, etc)
  • Based on OWIN middleware, ASP.NET Identity has no System.Web dependency

You can watch a video of Pranav Rastogi and I upgrading the ASP.NET Membership systems on an older ASP.NET application to the latest bits. There's also migration docs in detail:

ASP.NET Identity is on CodePlex today (and soon to be open sourced...paperwork) at https://aspnetidentity.codeplex.com/ or access the NuGet feed for nightly builds.

Adding Two-Factor authentication to an ASP.NET application

I recently changed all my accounts online to two-factor auth, and I really recommend you do as well. Here's how to add Two-Factor Auth to an ASP.NET application using Identity 2.0.

You'll have a class that is a UserManager that handles access to users and how they are stored. Inside this manager there's an IIdentityMessageService that you can implement to validate a user with whatever you want, like email, SMS, or a time-based token.

Send Verification Code

Here's an example SmsService where I'm using Twilio to send text messages. Again, you can do whatever you want in your implementation.

public class SmsService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
// Plug in your sms service here to send a text message.
message.Destination = Keys.ToPhone; //your number here
var twilio = new TwilioRestClient(Keys.TwilioSid, Keys.TwilioToken);
var result = twilio.SendMessage(Keys.FromPhone, message.Destination, message.Body);

return Task.FromResult(0);
}
}

If I were sending an EmailMessage, I'd do something like this. Note it's just another implementation of the same simple interface:

public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
string text = message.Body;
string html = message.Body;
//do whatever you want to the message
MailMessage msg = new MailMessage();
msg.From = new MailAddress("scott@hanselman.com");
msg.To.Add(new MailAddress(message.Destination));
msg.Subject = message.Subject;
msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(text, null, MediaTypeNames.Text.Plain));
msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(html, null, MediaTypeNames.Text.Html));

SmtpClient smtpClient = new SmtpClient("smtp.whatever.net", Convert.ToInt32(587));
System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(Keys.EmailUser, Keys.EMailKey);
smtpClient.Credentials = credentials;
smtpClient.Send(msg);

return Task.FromResult(0);
}
}

In your IdentityConfig.cs you can register as many TwoFactorProviders as you'd like. I'm adding both Email and Sms here. They include token providers but again, everything is pluggable.

manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<ApplicationUser> {
MessageFormat = "Your security code is: {0}"
});
manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser> {
Subject = "SecurityCode",
BodyFormat = "Your security code is {0}"
});

manager.EmailService = new EmailService();
manager.SmsService = new SmsService();

If a user tries to login you need to make sure they are a VerifiedUser. If not, get a valid two factor provider and send them a code to validate. In this case, since there are two providers to choice from, I let them pick from a dropdown. Here's the POST to /Account/SendCode:

public async Task<ActionResult> SendCode(SendCodeViewModel model)
{
// Generate the token and send it
if (!ModelState.IsValid)
{
return View();
}

if (!await SignInHelper.SendTwoFactorCode(model.SelectedProvider))
{
return View("Error");
}
return RedirectToAction("VerifyCode", new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl });
}

The sender of the two factor code depends on your implementation, of course.

public async Task<bool> SendTwoFactorCode(string provider)
{
var userId = await GetVerifiedUserIdAsync();
if (userId == null)
{
return false;
}

var token = await UserManager.GenerateTwoFactorTokenAsync(userId, provider);
// See IdentityConfig.cs to plug in Email/SMS services to actually send the code
await UserManager.NotifyTwoFactorTokenAsync(userId, provider, token);
return true;
}

When it's time to get the code from them, they need to have logged in with name and password already, and we're now checking the code:

[AllowAnonymous]
public async Task<ActionResult> VerifyCode(string provider, string returnUrl)
{
// Require that the user has already logged in via username/password or external login
if (!await SignInHelper.HasBeenVerified())
{
return View("Error");
}
var user = await UserManager.FindByIdAsync(await SignInHelper.GetVerifiedUserIdAsync());
return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl });
}

We can sign users potentially a number of ways, like with External Sign Ins (Twitter, etc) but here's the TwoFactorSignIn

public async Task<SignInStatus> TwoFactorSignIn(string provider, string code, bool isPersistent, bool rememberBrowser)
{
var userId = await GetVerifiedUserIdAsync();
if (userId == null)
{
return SignInStatus.Failure;
}
var user = await UserManager.FindByIdAsync(userId);
if (user == null)
{
return SignInStatus.Failure;
}
if (await UserManager.IsLockedOutAsync(user.Id))
{
return SignInStatus.LockedOut;
}
if (await UserManager.VerifyTwoFactorTokenAsync(user.Id, provider, code))
{
// When token is verified correctly, clear the access failed count used for lockout
await UserManager.ResetAccessFailedCountAsync(user.Id);
await SignInAsync(user, isPersistent, rememberBrowser);
return SignInStatus.Success;
}
// If the token is incorrect, record the failure which also may cause the user to be locked out
await UserManager.AccessFailedAsync(user.Id);
return SignInStatus.Failure;
}

If you want this blog post's sample code, make an EMPTY ASP.NET Web Application and run this NuGet command from the Package Manager Console

Install-Package Microsoft.AspNet.Identity.Samples -Pre

Have fun!

Related Links

* Photo of German Lorenz cipher machine by Timitrius used under CC Attribution 


Sponsor: Big thanks to Novalys for sponsoring the blog feed this week! Check out their security solution that combines authentication and user permissions. Secure access to features and data in most applications & architectures (.NET, Java, C++, SaaS, Web SSO, Cloud...). Try Visual Guard for FREE.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Page 1 of 35 in the ASP.NET MVC category Next Page

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.