Some Visual Studio Productivity Tips

  • Use Browser Link which uses SignalR to refresh browsers linked to your project.
  • Create your own Scaffolded Item.  When you Add -> New Item…, there is also option New Scaffolded Item….  You can add your new scaffolded item as one of the options.  You can copy and modify existing scaffolded items found at C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates (for Visual Studio 2017).  Copy folder you want to modify and paste it under CodeTemplates folder under your project root.  Make sure names of folders/files are intact so Visual Studio can pick them up.
  • Install Web Essentials extensions which provides the ultimate web development experience, such as the Browser Reload on Save, CSS Tools, HTML Tools, and ZenCoding.  Note that the design and inspect modes under Browser Link for Visual Studio 2017 is missing so you will need to download a separate extension for this, the Browser Link Inspector.
  • Use Visual Studio shortcut keys, such as Alt+1 and Shift+Alt+W.
  • Use ‘&’ intellisense to insert character entities on html/razor pages, as well as intellisense on bootstrap ‘data-‘ attributes, on angular directives ‘ng-‘, on angular templates or handle bars, and on web.config rewrite rules.
  • Use CSS editor tricks such as hover on CSS property to show browser support matrix.
  • Use LESS which extends CSS with features such as variables, mixins, and nested rules.
  • Install SideWaffle extension which provides useful snippets, project and item templates.  Unfortunately as of the time of this post, Visual Studio 2017 version is still under development.
Advertisements

Ways to Extend The ASP.NET MVC 5 Framework

ASP.NET MVC 5 Framework does not limit you to the capabilities it provide out of the box.  It is an extensible framework which emphasizes on convention over configuration or coding by convention, and below are some ways you can extend it.

  • Action Results
    • Action results are returned by the controller (e.g. return View()).
    • They are responsible for writing response to a request.
    • They are executed internally by MVC to write out the response.
    • You can create a custom action result by inheriting from ActionResult and overriding ExecuteResult(), or by extending an existing action result (e.g. FileResult).
  • Action Filters
    • Action filters execute before and after a controller action method.
    • You can create a custom action filter by implementing ActionFilter‘s OnActionExecuting() and OnActionExecuted() methods.
    • They can be applied at the method, controller, or global scope.
  • Helper Methods
    • Two types: inline Razor helpers (@helper) and HTML helpers (@Html.*).
    • They reduce code duplication but if it involves complex logic consider using partial view / child action method.
    • You can create your own HTML helper by creating an extension method to HTMLHelper.
  • View Engines
    • When controller returns a view, the MVC executes the action result and in the process uses a view engine to find a view and returns a ViewEngineResult whose Render() method is called.
    • A custom view engine can be used to extend view selection functionality such as to implement swappable UI themes (e.g. WordPress themes).
    • You create a custom view engine by extending the RazorViewEngine and in the constructor setting the search location format properties to use the theme directories that you want the view engine to search for for the currently active theme.
    • You register the custom view engine in Application_Start() calling ViewEngines.Engines.Insert(), inserting it as the first engine to be evaluated.  You can leave the RazorViewEngine there if you want a fallback.  Note that MVC supports multiple view engines.
  • Exception Filters
    • Exception filters catch errors that occur inside the scope of action method execution (including inside action filters and action results) and thus provide more contextual framework information.
    • The default exception filter in MVC is the HandleErrorAttribute.
    • You can create a custom exception filter by implementing the IExceptionFilter‘s OnException().
    • They can be applied at the method, controller, or global scope.
    • The ExceptionHandled flag is useful when using multiple exception filters: checking to make sure exception was not handled by previous exception filter before continuing.
    • Application_Error() should still be implemented as a fallback.
  • Server-Side Validations
    • Two ways: via data attributes (e.g. Required, Range, etc.) and implementation of IValidatableObject‘s Validate() in the model class, the former being reusable while the latter providing easy cross property validation.
    • The model binder that binds the request data to the model classes (or the action method parameters) checks the data attributes first then the Validate() and populates the controller’s ModelState property which you can check if any errors occurred in the model binding process (e.g. ModelState.IsValid).
    • You can create a custom data attribute by inheriting from ValidationAttribute and overriding IsValid() and setting the ErrorMessage in the constructor.
    • You can implement the IValidatableObject‘s Validate() in the model class and return List containing any error messages.
  • Model Binders
    • A model binder implements the IModelBinder‘s BindModel().  The binder model is returned by a model binder provider that implements IModelBinderProvider‘s GetBinder().  The model binding process searches through a list of model binder providers asking them if they can provide a model binder for the data it is trying to bind.
    • You can create a custom model binder by implementing IModelBinder‘s BindModel() and adding any error messages to the controller’s ModelState.  Then you create a custom model binder provider by implementing IModelBinderProvider‘s GetBinder() to return the custom model binder you just created.  You register your custom model binder provider in Application_Start() by calling ModelBinderProviders.BinderProviders.Insert().
  • Value Providers
    • A model binder employs value providers to provide it data from different sources such as posted form data, query string, route data, etc. that it can use to populate the action method parameters.
    • Possible uses of a custom value provider is to provide HTTP header data or settings from configuration file or database.
    • You create a custom value provider by implementing IValueProvider‘s two methods: ContainsPrefix() to return true if the passed in property name matches any data the custom value provider provides and GetValue() to return the value itself.  Then you create a custom value provider factory by inheriting from ValueProviderFactory and overriding GetValueProvider() to return the custom value provider you just created.  You register your custom value provider factory in Application_Start() by calling ValueProviderFactories.Factories.Insert().
  • Authentication Filters and Authorization Filters
    • Authentication filters implement IAuthenticationFilter‘s two methods: OnAuthentication() to authenticate a request and OnAuthenticationChallenge() that runs when authentication fails and right after action method execution.
    • Authorization filters implement IAuthorizationFilter‘s OnAuthorization().
    • These filters return a non-null context results if authentication/authorization fails.
    • Note that MVC supports Forms and Windows authentication by default and does not support Basic authentication.  One use of a custom authentication filter is to provide Basic authentication.
    • You create a custom authentication filter by implementing IAuthenticationFilter.  For custom authorization filter, consider inheriting from AuthorizeAttribute instead.
  • Action Name Selectors and Action Method Selectors
    • Action name selectors (e.g. [ActionName(“xxxxx”)]) and action method selectors (e.g. [HttpGet] and [HttpPost]) influence the decision process of selecting which action method to handle the request by the action invoker.
    • You can create a custom action name selector by inheriting from ActionNameSelectorAttribute and overriding IsValidName().
    • You can create a custom action method selector by inheriting from ActionMethodSelectorAttribute and overriding IsValidForRequest().

 

Additional References:

 

BONUS: Found this good article worth looking too: 10 ways to extend your Razor views in ASP.​NET core – the complete overview.

ASP.NET MVC 5: OWIN/Katana Pipeline And Middleware Components (A Demo)

DEMO | CODE | MY (Other) PROJECTS

If you know ASP.NET Core, you will notice some similarities between that and Katana.  That is because both of them supports OWIN: Katana bringing OWIN support to ASP.NET; and ASP.NET Core natively supporting OWIN.

In this demo, using ASP.NET MVC 5, I registered my OWIN middleware components in the Configuration(IAppBuilder) method of the Startup class declared in Startup.cs by calling one of the these methods: IAppBuilder.Use(), or an IAppBuilder extension method that wraps IAppBuilder.Use(),  or IAppBuilder.Run().  This code explains it a little bit more.

I declared all my OWIN components in a separate file named Startup.MyOWINComponents.cs.  Each component adds a Hello World!!! string in their own language to an OWIN environment variable and awaits the next component in the pipeline, and once the last component is done it passes control back to the previous component until the first component in the pipeline outputs the resulting string to response.  This code explains it a little bit more.

The demo displays the following:

Hello World!!!
Bonjour Tout Le Monde!!!
Mabuhay!!!

 

A Custom WebGrid (My 1st Iteration)

DEMO | CODE

To display tabular data in ASP.NET MVC (I’m using MVC 4 at the time), I used the web helper WebGrid.  It has sorting and paging but no filtering.  Also sorting and paging is only client-side and not server-side, meaning all the data is requested from the server and sorted and paged on the client.  Because of these limitations I had to customize WebGrid and this demo is my first iteration.

Here in this demo I used Entity Framework to get my data access layer going.  I used the Adventure Works 2008R2 SQL database, the light version.  Here I am displaying the Products table.  To get my UI going, I used the default template that comes with Visual Studio 2010 and it uses jQuery UI.  My second iteration of this custom WebGrid will be using Bootstrap and is still in the works, just FYI.

If you find that you cannot reference WebGrid in your view, there is a chance that System.Web.Helpers is not added to your References.  Add that and set Copy Local to True.  Search Google if you are having problems with this.

You can copy and paste the code into your own project but you have to change the column names in the WebGrid, add these same columns to sort on in the controller, and change the fields you want to filter on in both view and controller.  Also, you can change the default page size in the FilterSortPageInfo class.  Oh by the way, this is a read-only WebGrid and there is no edit or add functionality.  Cheers!

The Very Basic Syntax of Razor

If you have worked in ASP.NET MVC, you know that the default view engine (or templating engine) is Razor, much like the .aspx/.ascx/.master file templates in ASP.NET Web Forms.  One thing I like about Razor is that you can use C# or VB.NET as the programming language to code in Razor.  All you need to do is learn how to use the Razor syntax.

So here I present to you the very basic syntax you need to know about Razor.  In the code below I am using C#, my preferred language.  You can view the generated HTML page here.

<div>
    
<h1>Razor Demo Using C#</h1>
    
@*  
   Razor comments can be one line or multiple lines.
   Unlike HTML comments, Razor comments are not rendered to the page.
*@
    
@{
   @* You can add Razor comments inside the Razor code block such as this. *@
}
    
@{
   // But why use Razor comments when you can use C# comments.
   /*
    * C# multi-line comment
    */
}
    
@*  
   Razor code starts with @ character.
   It can be a single statement block, an inline expression,
    or a multi-statement block.
   Once you start your code with @, all of the .NET framework,
    ASP.NET, and all the C# features are available to you.
*@
    
@* An example of a Razor single statement block: *@
@{ var myGreeting = "<Hello, World!>"; } 
    
@* 
   Below is an example of a Razor inline expression.
   Note that the output from server code is automatically HTML-encoded.
    < and > characters in the variable myGreeting will automatically
    be encoded to &lt; and &gt; so it can be displayed properly
    in the browser.  You can check the page source to verify this.
*@
<p>The value of myGreeting is: @myGreeting</p>
    
@* 
   A Razor inline expression can be multi-token if enclosed in ()
    as in example below.
   Note that () can also be used to explicitly declare a Razor
    inline expression.
*@
<p>@("The value of myGreeting is: " + myGreeting)</p>
    
@* Here is an example of a Razor multi-statement block *@
@{
    var myGreeting2 = "Hello, Universe!";
    var myDate = DateTime.Today.ToString("MMMM dd, yyyy");   
}
    
<p>@myGreeting2 Today is @myDate.</p>
    
@*
    You will notice in the previous examples of Razor code blocks, 
     be they single or multi-statement blocks, are enclosed in {}.
     They don't have to be always enclosed in {}.
     Take for example the if statement below.  
     Since it is essentially a single statement, 
     it can follow the @ character immediately.
     The same goes with for, foreach, switch, etc.
*@
    
@{ var myMsg = ""; }
    
@if (IsPost) 
{
    myMsg = "This is a postback!";
}
else
{
    myMsg = "This is not a postback.";
}
 
<p>@myMsg<p>
    
@*
    You can also mix text and markup in the code block.
*@
    
@if (true)
{
    // Mixing markup in code is as easy as putting in the matching HTML tags.
    <p>The value of IsPost is: @IsPost</p>
    
    // You can use @: or <text> to render plain text.
    // If you check the page source, these plain texts are not enclosed in
    //  any HTML tags.
    @:This is plain text.
    <br />
    <text>Another plain text.</text>
    <br />
    <br />
}
    
</div>

Additional Resources: