Monthly Archives: January 2014

Microsoft BizTalk Server Explained in Simple Terms

watch ARTICLE TAKEN FROM:http://blogs.technet.com/b/clint_huffman/archive/2009/03/18/microsoft-biztalk-server-explained-in-simple-terms.aspx

At TechEd 2008, I manned the Microsoft BizTalk Server booth. Nearly every question I got was, “I’ve heard of BizTalk, but what does it do?”. If you are like me 3 years ago which is sounds like many people are, I wish someone would have just came out and given me a simple description of BizTalk. Now that I know BizTalk, here is the *simple* description/FAQ of what it is and why it is a great product.

What is BizTalk?

BizTalk is a message conversion system. You give it MessageA and it converts it to MessageB. For example, if MessageA is an EDI (Electronic Data Interchange) message, then BizTalk is able to easily read the message and convert it into just about any other message type such as an XML document (MessageB). Will it convert a Word document to a PDF document? It can, but it was really designed to allow businesses to easily communicate with each other using practically any message format and nearly any network protocol.

I can just code this in .NET why do I need BizTalk?

Sure, you can fire up Visual Studio and write this on your own, but did you think about guaranteed delivery, disaster recovery, tracking, troubleshooting, security, or authentication? What if the network protocol to receive and send these messages needs to change? How long would it take to change your custom application compared to a simple configuration change (no recompile necessary) in BizTalk. When you keep creating monolithic applications to handle your business to business (B2B) transactions, it becomes increasingly difficult to manage it and you find yourself trying to write an infrastructure to handle it. BizTalk provides all of this infrastructure for you. It has guaranteed delivery, standardized tracking, a business rules engine, redundancy, and much more.

I am not doing B2B. Is BizTalk still helpful?

Yes. Many people use BizTalk as an integration platform – meaning all of those old systems that you have that don’t communicate with each other can be bridged together with BizTalk. The marketing term for this is Solution Oriented Architecture (SOA). Also, many companies love BizTalk so much that all of their business logic internally in their company flows through it with the confidence of BizTalk’s ability to make nearly any business process a structured transaction.

BizTalk is *huge*, do I really need all of that infrastructure?

BizTalk is not for everyone. Again, you can certainly write your own .NET application to do very basic message conversion, but once your company matures and needs enterprise level messaging, reliability, and flexibility, then that is when you get BizTalk.

What is BizTalk really good at?

BizTalk is great when dealing with frequent changes in how you do business with other businesses. For example, if you deal with a lot of businesses that have different message requirements, frequent network protocol changes, then BizTalk is for you. Also, many customers really like how easy it is to map the schemas of messages. For example, FName in MessageA can be easily mapped to FirstName in MessageB regardless of how the messages are structured.

You keep talking about “messaging”. Does this mean that BizTalk does email?

The messaging we are talking about would be something like reading in a purchase order from CompanyA and sending the order to your fulfillment and shipping departments. BizTalk can also send email if you want it to, but it’s really designed to get businesses to talk to each other hence why it is called “Biz-Talk”.

Additional Information

One of my colleagues at Microsoft requested that I include information on some of the other features that BizTalk Server provides:

  • Multiple adapters provide support for most industry standard transports (FTP, HTTP, File, SOAP, WCF, SQL, etc.)
  • Multiple accelerators are available that support for industry standard document formats (HIPAA, EDI, SWIFT)
  • RFID Platform
  • High availability
  • Fault tolerance
  • Scalability
  • End to end message tracking (including message body tracking if needed.
  • Messaging subsystem accommodates transactional messaging, i.e. BizTalk can send to/receive from trading partners within the context of a distributed transaction as long as the adapter supports transactions.
  • XLANGs workflow engine
  • Business Activity Monitoring
  • Business Rule Engine (BRE)
  • Management functionality via Management console
  • Integration with MOM
  • Integration with Enterprise Single Sign-On

These features are available in BizTalk Server, which allows you to quickly integrate your business processes with other internal business processes and with external trading partners.  Several of these features are described in further detail athttp://www.microsoft.com/biztalk/en/us/capabilities.aspx.

Thanks to Trace Young (BizTalk Technical Writer) for this bit of information.

New MCSD: Web Applications certification!

Today’s customers expect high-quality, interactive line-of-business and consumer applications. With Visual Studio 2012, developers can use a single integrated solution to create modern, interactive web applications that seamlessly integrate with data-driven services.  The MCSD: Web Applications certification is for developers who want the skills to build applications demanded in today’s market using MVC, Azure, HTML5, and CSS3.

Candidates must pass the following three exams to earn the MCSD: Web Applications certification:

Earning an MCSD: Web Applications certification helps developers build the skills needed to create tomorrow’s apps and provides a competitive advantage in the industry. Developers who achieve this challenging certification must regularly demonstrate their up-to-date and relevant skills on rapidly changing development technologies through recertification. The certifications will be achievable when the final versions of the exams release in mid-October.

original article:http://borntolearn.mslearn.net/btl/b/weblog/archive/2012/08/07/new-mcsd-web-applications-certification.aspx#fbid=PDmDoKR3Uic

Programatically checkin file to TFS using C#

original Article at :http://blogs.msdn.com/b/buckh/archive/2012/03/10/team-foundation-version-control-client-api-example-for-tfs-2010-and-newer.aspx

Over six years ago, I posted a sample on how to use the version control API.  The API changed in TFS 2010, but I hadn’t updated the sample.  Here is a version that works with 2010 and newer and is a little less aggressive on clean up in the finally block.

This is a really simple example that uses the version control API.  It shows how to create a workspace, pend changes, check in those changes, and hook up some important event listeners.  This sample doesn’t do anything useful, but it should get you going.

You have to supply a Team Project as an argument.

The only real difference in this version is that it uses the TeamFoundationServer constructor (in beta 3, you were forced to use the factory class).

You’ll need to add references to the following TFS assemblies to compile this example.

Microsoft.TeamFoundation.VersionControl.Client.dll
Microsoft.TeamFoundation.Client.dll

 

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Text;
  6. using Microsoft.TeamFoundation.Client;
  7. using Microsoft.TeamFoundation.VersionControl.Client;
  8. namespace BasicSccExample
  9. {
  10.     class Example
  11.     {
  12.         static void Main(string[] args)
  13.         {
  14.             // Verify that we have the arguments we require.
  15.             if (args.Length < 2)
  16.             {
  17.                 String appName =Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
  18.                 Console.Error.WriteLine(“Usage: {0} collectionURL teamProjectPath”, appName);
  19.                 Console.Error.WriteLine(“Example: {0} http://tfsserver:8080/tfs/DefaultCollection $/MyProject”, appName);
  20.                 Environment.Exit(1);
  21.             }
  22.             // Get a reference to our Team Foundation Server.
  23.             TfsTeamProjectCollection tpc = newTfsTeamProjectCollection(new Uri(args[0]));
  24.             // Get a reference to Version Control.
  25.             VersionControlServer versionControl = tpc.GetService<VersionControlServer>();
  26.             // Listen for the Source Control events.
  27.             versionControl.NonFatalError +=Example.OnNonFatalError;
  28.             versionControl.Getting += Example.OnGetting;
  29.             versionControl.BeforeCheckinPendingChange +=Example.OnBeforeCheckinPendingChange;
  30.             versionControl.NewPendingChange +=Example.OnNewPendingChange;
  31.             // Create a workspace.
  32.             Workspace workspace = versionControl.CreateWorkspace(“BasicSccExample”, versionControl.AuthorizedUser);
  33.             String topDir = null;
  34.             try
  35.             {
  36.                 String localDir = @”c:\temp\BasicSccExample”;
  37.                 Console.WriteLine(“\r\n— Create a mapping: {0} -> {1}”, args[1], localDir);
  38.                 workspace.Map(args[1], localDir);
  39.                 Console.WriteLine(“\r\n— Get the files from the repository.\r\n”);
  40.                 workspace.Get();
  41.                 Console.WriteLine(“\r\n— Create a file.”);
  42.                 topDir =Path.Combine(workspace.Folders[0].LocalItem, “sub”);
  43.                 Directory.CreateDirectory(topDir);
  44.                 String fileName = Path.Combine(topDir,”basic.cs”);
  45.                 using (StreamWriter sw = newStreamWriter(fileName))
  46.                 {
  47.                     sw.WriteLine(“revision 1 of basic.cs”);
  48.                 }
  49.                 Console.WriteLine(“\r\n— Now add everything.\r\n”);
  50.                 workspace.PendAdd(topDir, true);
  51.                 Console.WriteLine(“\r\n— Show our pending changes.\r\n”);
  52.                 PendingChange[] pendingChanges = workspace.GetPendingChanges();
  53.                 Console.WriteLine(”  Your current pending changes:”);
  54.                 foreach (PendingChange pendingChange inpendingChanges)
  55.                 {
  56.                     Console.WriteLine(”    path: ” + pendingChange.LocalItem +
  57.                                       “, change: ” +PendingChange.GetLocalizedStringForChangeType(pendingChange.ChangeType));
  58.                 }
  59.                 Console.WriteLine(“\r\n— Checkin the items we added.\r\n”);
  60.                 int changesetNumber = workspace.CheckIn(pendingChanges, “Sample changes”);
  61.                 Console.WriteLine(”  Checked in changeset ” + changesetNumber);
  62.                 Console.WriteLine(“\r\n— Checkout and modify the file.\r\n”);
  63.                 workspace.PendEdit(fileName);
  64.                 using (StreamWriter sw = newStreamWriter(fileName))
  65.                 {
  66.                     sw.WriteLine(“revision 2 of basic.cs”);
  67.                 }
  68.                 Console.WriteLine(“\r\n— Get the pending change and check in the new revision.\r\n”);
  69.                 pendingChanges = workspace.GetPendingChanges();
  70.                 changesetNumber = workspace.CheckIn(pendingChanges, “Modified basic.cs”);
  71.                 Console.WriteLine(”  Checked in changeset ” + changesetNumber);
  72.             }
  73.             finally
  74.             {
  75.                 if (topDir != null)
  76.                 {
  77.                     Console.WriteLine(“\r\n— Delete all of the items under the test project.\r\n”);
  78.                     workspace.PendDelete(topDir,RecursionType.Full);
  79.                     PendingChange[] pendingChanges = workspace.GetPendingChanges();
  80.                     if (pendingChanges.Length > 0)
  81.                     {
  82.                         workspace.CheckIn(pendingChanges, “Clean up!”);
  83.                     }
  84.                     Console.WriteLine(“\r\n— Delete the workspace.”);
  85.                     workspace.Delete();
  86.                 }
  87.             }
  88.         }
  89.         internal static void OnNonFatalError(Object sender,ExceptionEventArgs e)
  90.         {
  91.             if (e.Exception != null)
  92.             {
  93.                 Console.Error.WriteLine(”  Non-fatal exception: “+ e.Exception.Message);
  94.             }
  95.             else
  96.             {
  97.                 Console.Error.WriteLine(”  Non-fatal failure: ” + e.Failure.Message);
  98.             }
  99.         }
  100.         internal static void OnGetting(Object sender,GettingEventArgs e)
  101.         {
  102.             Console.WriteLine(”  Getting: ” + e.TargetLocalItem +”, status: ” + e.Status);
  103.         }
  104.         internal static void OnBeforeCheckinPendingChange(Objectsender, ProcessingChangeEventArgs e)
  105.         {
  106.             Console.WriteLine(”  Checking in ” + e.PendingChange.LocalItem);
  107.         }
  108.         internal static void OnNewPendingChange(Object sender,PendingChangeEventArgs e)
  109.         {
  110.             Console.WriteLine(”  Pending ” +PendingChange.GetLocalizedStringForChangeType(e.PendingChange.ChangeType) +
  111.                               ” on ” + e.PendingChange.LocalItem);
  112.         }
  113.     }
  114. }

Using Bootstrap Tooltips to display jQuery Validation error messages

Using Bootstrap Tooltips to display jQuery Validation error messages

I love jQuery Validation. I was recently putting together a screen which had a lot of different bits of validation going on. And the default jQuery Validation approach of displaying the validation messages next to the element being validated wasn’t working for me. That is to say, because of the amount of elements on the form, the appearance of validation messages was really making a mess of the presentation. So what to do?

<!DOCTYPE 2014-01-03_1355html>
<html lang=”en”>
<head>
<meta charset=”utf-8″ />
<link href=”//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css” rel=”stylesheet”>
<style>
form { padding: 10px; }
.error { border: 1px solid #b94a48!important; background-color: #fee!important; }
</style>
</head>
<body>
<form>
<div class=”row”>
<label for=”RequiredDateDemo”>A date is required (eg “15 June 2012”):</label>
<input
data-msg-date=”The field RequiredDateDemo must be a date.”
data-msg-required=”The RequiredDateDemo field is required.”
data-rule-date=”true”
data-rule-required=”true”
id=”RequiredDateDemo” name=”RequiredDateDemo” type=”text” value=”” />
</div>
<div class=”row”>
<label for=”StringLengthAndRequiredDemo”>A string is required between 5 and 10 characters long:</label>
<input
data-msg-maxlength=”The field StringLengthAndRequiredDemo must be a string with a minimum length of 5 and a maximum length of 10.”
data-msg-minlength=”The field StringLengthAndRequiredDemo must be a string with a minimum length of 5 and a maximum length of 10.”
data-msg-required=”The StringLengthAndRequiredDemo field is required.”
data-rule-maxlength=”10″
data-rule-minlength=”5″
data-rule-required=”true”
id=”StringLengthAndRequiredDemo” name=”StringLengthAndRequiredDemo” type=”text” value=”” />
</div>
<div class=”row”>
<label for=”RangeAndNumberDemo”>Must be a number between -20 and 40:</label>
<input
data-msg-number=”The field RangeAndNumberDemo must be a number.”
data-msg-range=”The field RangeAndNumberDemo must be between -20 and 40.”
data-rule-number=”true”
data-rule-range=”[-20,40]”
id=”RangeAndNumberDemo” name=”RangeAndNumberDemo” type=”text” value=”-21″ />
</div>
<div class=”row”>
<label for=”RangeAndNumberDemo”>An option must be selected:</label>
<select
data-msg-required=”The DropDownRequiredDemo field is required.”
data-rule-required=”true”
id=”DropDownRequiredDemo” name=”DropDownRequiredDemo”>
<option value=””>Please select</option>
<option value=”An Option”>An Option</option>
</select>
</div>
<div class=”row”>
<button type=”submit”>Validate</button>
</div>
</form>
<script src=”//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.js” type=”text/javascript”></script>
<script src=”//ajax.aspnetcdn.com/ajax/jQuery.validate/1.11.1/jquery.validate.js” type=”text/javascript”></script>
<script src=”//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js”></script>
<script type=”text/javascript”>
$(“form”).validate({
showErrors: function(errorMap, errorList) {
// Clean up any tooltips for valid elements
$.each(this.validElements(), function (index, element) {
var $element = $(element);
$element.data(“title”, “”) // Clear the title – there is no error associated anymore
.removeClass(“error”)
.tooltip(“destroy”);
});
// Create new tooltips for invalid elements
$.each(errorList, function (index, error) {
var $element = $(error.element);
$element.tooltip(“destroy”) // Destroy any pre-existing tooltip so we can repopulate with new tooltip content
.data(“title”, error.message)
.addClass(“error”)
.tooltip(); // Create a new tooltip based on the error messsage we just set in the title
});
},
submitHandler: function(form) {
alert(“This is a valid form!”);
}
});
</script>
</body>
</html>

ASP.Net MVC Validation Using Fluent Validation

This article explains how to implement ASP.NET MVC validation using Fluent Validation. Fluent validation is a small validation library for .NET that uses a Fluent interface and lambda expressions for building validation rules for your business objects.  Fluent validation is one way of setting up dedicated validator objects, that you would use when you want to treat validation logic as separate from business logic. The Aspect-Oriented Programming (AOP) paradigm enables separation of cross-cutting concerns within a system, and validation is one such concern. Separating validation helps clean up your domain code and make it more cohesive, as well as giving you a single place to look for validation logic.

I create a Customer model (Customer class under Models folder) that has two properties, one is “Email” and another is “Name” as in the following code snippet:

namespace MvcValidation.Models

{

    public class Customer

    {

        public string Name { get; set; }

        public string Email { get; set; }

    }

}

Now I install the Fluent validation Nuget package in the application so I can use Fluent validation rules.

Figure 1.1 Install FluentValidation NuGet package

After that I create a validator class for the Customer model under the “Validators” folder but you can create it anywhere in an application for validation rules on Customer properties. I used two rules, one is not empty and another validates an email address.

using FluentValidation;

using MvcValidation.Models;

 

namespace MvcValidation.Validators

{

    public class CustomerValidator : AbstractValidator<Customer>

    {

        public CustomerValidator()

        {

            RuleFor(x => x.Name).NotEmpty().WithMessage(“Name is required”);

            RuleFor(x => x.Email).NotEmpty().WithMessage(“Email is required”);

            RuleFor(x => x.Email).EmailAddress().WithMessage(“Email is not valid”);               

        }

    }

}

After that, you need to create a controller’s action methods; these render views on the UI and binds a model with the view. So let’s create a controller with two action methods; these handle both request types (GET and POST) respectively.

using System.Web.Mvc;

using FluentValidation.Results;

using MvcValidation.Models;

using MvcValidation.Validators;

 

namespace MvcValidation.Controllers

{

    public class CustomerController : Controller

    {

        public ActionResult Index()

        {

            return View();

        }

        [AcceptVerbs(HttpVerbs.Post)]

        public ActionResult Index(Customer model)

        {

            CustomerValidator validator = new CustomerValidator();

            ValidationResult result = validator.Validate(model);

            if (result.IsValid)

            {

                ViewBag.Name = model.Name;

                ViewBag.Email = model.Email;

            }

            else

            {

                foreach (ValidationFailure failer in result.Errors)

                {

                    ModelState.AddModelError(failer.PropertyName, failer.ErrorMessage);

                }               

            }

            return View(model);

        }

    }

}

Thereafter I create a view (Index.cshtml) for user input under the Customer folder.

@model MvcValidation.Models.Customer

@{

    ViewBag.Title = “Index”;

}

@if (ViewData.ModelState.IsValid)

{

    <b>Name : @ViewBag.Name<br />

        Email : @ViewBag.Email

    </b>       

}

@using (Html.BeginForm())

{    

    <fieldset>

        <legend>Customer</legend>

        <div class=”editor-label”>

            @Html.LabelFor(model => model.Name)

        </div>

        <div class=”editor-field”>

            @Html.EditorFor(model => model.Name)

            @Html.ValidationMessageFor(model => model.Name)

        </div>

        <div class=”editor-label”>

            @Html.LabelFor(model => model.Email)

        </div>

        <div class=”editor-field”>

            @Html.EditorFor(model => model.Email)

            @Html.ValidationMessageFor(model => model.Email)

        </div>

        <p>

            <input type=”submit” value=”Create” />

        </p>

    </fieldset>

}

@section Scripts {

    @Scripts.Render(“~/bundles/jqueryval”)

}


Let’s run the application and test the following scenario:

1. When all fields are empty:

Figure 1.2: Validation Message when both fields are empty

2. When the Name field is empty but Email is not valid:

Figure 1.3 : Validation Message when Email is not valid

3. When both fields are valid:

Figure 1.4 All fields are valid

ASP.NET MVC – Legacy Url Routing

  1. A legacy Url is requested from your site. For example, http://www.server.com/Users/Login.aspx
  2. ASP.NET routing intercepts the request and matches a route from your route collection
  3. Instead of using the MvcRouteHandler, a LegacyRouteHandler is invoked.
  4. Using the LegacyRouteHandler, it’ll use the route redirection name you specified, generate the MVC Url, and issue a HTTP 301 with the location of http://www.server.com/site/login.

Routing

First, we should define our legacy route class. This is necessary because we need to expose an additional property to enable our routing handler to find the correct MVC route.

   1: // The legacy route class that exposes a RedirectActionName
   2: public class LegacyRoute : Route {
   3:     public LegacyRoute(string url, string redirectActionName, IRouteHandler routeHandler)
   4:         : base(url, routeHandler)
   5:     {
   6:         RedirectActionName = redirectActionName;
   7:     }
   8:
   9:     public string RedirectActionName { get; set; }
  10: }

Secondly, we need to define the route handler and associated http handler. The route handler derives from IRouteHandler, and will be the class used when creating your legacy routing. The http handler derives from MvcHandler because it gives us some critical information, like RequestContext. You’ll also notice that (while not in the code) you need to copy all of the querystring parameters from the request over. This is a necessary step because the GetVirtualPath method call will take all route data (from RouteData.Values) and try and utilize that when building the Url itself.

   1: // The legacy route handler, used for getting the HttpHandler for the request
   2: public class LegacyRouteHandler : IRouteHandler {
   3:     public IHttpHandler GetHttpHandler(RequestContext requestContext) {
   4:         return new LegacyHandler(requestContext)
   5:     }
   6: }
   7:
   8: // The legacy HttpHandler that handles the request
   9: public class LegacyHandler : MvcHandler {
  10:     public LegacyHandler(RequestContext requestContext) : base(requestContext) { }
  11:
  12:     protected override void ProcessRequest(HttpContextBase httpContext) {
  13:         string redirectActionName = ((LegacyRoute)RequestContext.RouteData.Route).RedirectActionName;
  14:
  15:         // ... copy all of the querystring parameters and put them within RouteContext.RouteData.Values
  16:
  17:         VirtualPathData data = RouteTable.Routes.GetVirtualPath(RouteContext, redirectActionName, RouteContext.RouteData.Values);
  18:
  19:         httpContext.Status = "301 Moved Permanently";
  20:         httpContext.AppendHeader("Location", data.VirtualPath);
  21:     }
  22: }

Lastly, you need to create your routes within the Global.asax file. Remember, that order is necessary when setting up routing.

   1: public void RegisterRoutes(RouteCollection routes) {
   2:     routes.MapRoute("Login", "site/login", new {
   3:         controller = "Users",
   4:         action = "DisplayLogin"
   5:     });
   6:
   7:     routes.Add("", new LegacyRoute(
   8:         "Users/Login.aspx",
   9:         "Login",
  10:         new LegacyRouteHandler()));
  11: }

And that’s it. When a request comes in, you’ll see the following in Fiddler

  1. A request on “Users/Login.aspx”
  2. A HTTP 301, with a header “Location” and value of “site/login”
  3. A request on “site/login”

Final Thoughts

Granted, there’s more you can do with this – like creating your own extension methods like MapRoute and doing better handling of finding the route, but this should get you started. Also, I’m writing the code off the top of my head, so there’s no guarantee that any of it works as-is. Please let me know if you have any other thoughts.

 

Lastly, for those wondering why are we using a HTTP 301 status code? Well read up on them. “301 Moved Permanently” indicates “that all future requests should be directed to the given URI.” While your end users will not see any difference other than a new URL in the browser, the 301 status code more aimed towards search engines to update their URL’s in their indexes.

original article at:http://www.eworldui.net/blog/post/2008/04/ASPNET-MVC—Legacy-Url-Routing.aspx

301 redirects

While ASP.NET MVC has a powerful routing engine for handling requests, there can be a scenario when you need to process a list of specific URL rewrites in your application. Often this can be due to a new version of an existing site going live where the URL structure has changed. Under Apache, this can be handled easily in the .htaccess file of the site by listing out each path  you’d like to rewrite like so:

1
2
3
4
<IfModule mod_rewrite.c>
  RewriteEngine on
  Redirect 301 /somepage.html /otherpage.html
</IfModule>

It can also be handled in IIS 7 using the URL Rewrite module or under IIS 6 using a 3rd party extension such as Helicon ISAPI Rewrite.

But what if you want to handle the redirects via code?

Bulk 301 Redirect – Considerations

Our two main considerations when coming up with this solution were:

  1. We don’t want to check for a redirect on every request (just old broken links)*
  2. We don’t want to have to do a code push to change the 301 mapping list

buy furosemide for dogs *: You can use the same solution to process every request by changing the location of the 301 check

This led us down a path where we are capturing 404 requests in the application, then checking for a rewrite rule before actually displaying a 404 page. If the rule exists, we rewrite the path instead of showing the 404.

The 301 List

With consideration #2 in mind, we decided to use a flat file in the App_Data folder to hold our rewrite rules. The file is simple since all we are concerned with is permanent redirects. We use a plain old CSV file with 2 columns, the first column being the old path to check for, the second column is the new path to permanently redirect to. For example:

1
2
/Home/FollowUs,/About/Follow-Us
/Home/ContactUs,/About/contact-us

This makes constructing, updating, and maintaining the rewrite list extremely easy. Even better, since it’s a CSV file, you can use excel to have a non technical person create the list for you if it’s lengthy.

To process the list, we created a single static method to load the list into a key,value Dictionary object. Here is the entire class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
namespace CypressNorth.Data.Services
{
    public class FlatFileAccess
    {
        public static Dictionary<string,string> Read301CSV()
        {
            string file = "App_Data/301.csv";
            string path = System.IO.Path.Combine(AppDomain.CurrentDomain.GetData("DataDirectory").ToString(), file);
            if (File.Exists(path))
            {
                using (TextReader sr = new StreamReader(path))
                {
                    Dictionary<string,string> redirect_dict = new Dictionary<string,string>();
                    string line = "";
                    while ((line = sr.ReadLine()) != null)
                    {
                        string[] columns = line.Split(',');
                        redirect_dict.Add(columns[0], columns[1]);
                    }
                    return redirect_dict;
                }
            }
            else
                return null;
        }
    }
}

This will process your list of rewrite rules into a Dictionary<string,string> list and return it for you.

Intercepting 404 responses

Now that we have our list of 301 redirects and a way to access them, we need to hook into the app request life cycle to process them. Our consideration #1 states that we don’t want to process every single request to the site, just bad URL’s so the logical place for this is when a 404 response is encountered.

To hook into this we create a new method in the global.asax file. You could do this via an HttpModule as well if you prefer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected void Application_Error()
{
    Exception exception = Server.GetLastError();
    // Clear the error
    Response.Clear();
    Server.ClearError();
    if (exception is HttpException)
    {
        HttpException ex = exception as HttpException;
        if(ex.GetHttpCode() == 404)
        {
            var url = HttpContext.Current.Request.Path.TrimEnd('/');
            var redirect = FlatFileAccess.Read301CSV();
            if (redirect.Keys.Contains(url))
            {
                // 301 it to the new url
                Response.RedirectPermanent(redirect[url]);
            }
        }
    }
}

This method will catch Exceptions application wide. You can implement much more robust error handing using the same hook but for our purposes we just want to catch 404′s and check for redirects. So when an error is thrown in the application, the exception is checked to see if it is a 404 type HttpException. If it is, we load the 301.csv file and compare it against the requested path. If a match is found we 301 redirect the request to the new url. If it is not found, we let the error fall through.

ASP.NET Web API 2.1 RC is out

The ASP.NET team kept it’s frantic work pace and already before Christmas dropped onNuget a 2.1 RC of Web API (as well as new MVC and Web Pages).

While in the open source mode of operation (public commits, nightly builds) this is that big of a news, it is still a very nice piece of news. Let’s look at what’s new.

Overview of ASP.NET Web API 2.1 RC

The official release notes are available here. Most of the features you have already seen – as on this blog we try to cover both existing and the upcoming bits of the Web API framework.

You can grab the release from Nuget:

Shell
1
Install-Package Microsoft.AspNet.WebApi -Pre

 

Glboal error handling

Arguably the biggest feature of this drop – something that has been very heavily discussed i nthe advisors meetings and in the discussion list.

The full feature specification is available here.

Now, in short, you get a single point of error handling for your Web API – something that didn’t exist before, and trying to handle all errors required you to catch in many places (or resort toGlobal.asax).

Up to this point you could use ExceptionFilters for more or less widely-scoped error handling; but they wouldn’t catch exceptions from message handlers, media type formatters or routing.

The simplest example is absolutely trivial:

C#
1
2
3
4
5
6
7
public class TraceExceptionLogger : ExceptionLogger
{
    public override void LogCore(ExceptionLoggerContext context)
    {
        Trace.TraceError(context.ExceptionContext.Exception.ToString());
    }
}

 

BSON formatter

Web API now supports application/bson out of the box. We have written a BSON formatter on this blog back in the summer of 2012 and it’s also a part of WebApiContrib, but it’s nice to have it in the core, especially as it doesn’t bring in any external dependencies (it relies on JSON.NET).

It has also been hardedned a bit, so that’s another plus.

Async filters

I have just recently blogged about async filters for Web API. As mentioned there, the vNext will have it in the box, and as a result, you can enjoy this feature in Web API 2.1 RC.

Ignore routes

HttpRoutesCollection will now support IgnoreRoute mechanism, allowing you to easily exclude parts of your routing hierarchy from being matched.

Attribute routing enhancements

Attribute routing now provides new extensibility hooks. They are described in detail here (bottom of the page) and allow you to provide instructions on custom route resolution (IDirectRouteProvider). This is extremely useful when trying to do something like versioning or localization.

Fixes, fixes, fixes

Plenty of bug fixes too. Among the more interesting ones:

Web API 2’s Attribute Routing: Looking Deeper

While most of us are used to creating routes using the Web API configuration, attributed routes are different. Before attributed routing, when you would look at the route data (e.g.  buy atarax syrup request.GetRouteData()) you would get a route with a name that tied to the configured name. This was really useful for the way to use  UrlHelper to build your URLs.

In fact, you can get this behavior by supplying names to the individual routes in your attributed routing:

1
2
3
4
5
6
7
8
9
10
11
12
13
public FooController : ApiController
{
  [Route("api/foos", Name = "Foo")]
  public object Get()
  {
    // ...
  }
}
...
var helper = new UrlHelper(Request);
var url = helper.Link("Foo");

But if you’re traversing the route collection in any way (e.g. in a bentyl buy online  ControllerSelector) it is important to understand where these routes actually are. When you use attribute routing, all the route attributes get added to a common route without a name. This is a special route that is an instance of an internal class called RouteCollectionRoute (Source Link). This route has a collection of sub-routes that you can query for that includes *all* the attribute routes. But if you just want the selected route for your call, you can simple ask for it using the RouteData.Values:

1
2
3
var routeData = request.GetRouteData();
var subroutes = (IEnumerable<IHttpRouteData>)routeData.Values["MS_SubRoutes"];
var route = subroutes.First().Route;

The real problem for some is that there is no longer controller name in the route data. This makes sense of course because there is no specific controller that a route points to as attributed routes are related to methods, not controllers. Being aware of these internals may help you solve issues when you use or move to using attributed routes.

Top 5 New Features in ASP.NET Web API 2

ASP.NET Web API 2 has been released with a number of new exciting features.

1. Attribute Routing

Along with convention-based routing, Web API 2 now supports attribute routing as well.

In case of convention-based routing, we can define multiple route templates. When a request comes, it will be matched against already defined route templates, and forwarded to specific controller action according to matched template.

You can see the following default route template in routing table for Web API:

Config.Routes.MapHttpRoute(
name: “DefaultApi”,
routeTemplate: “api/{Controller}/{id}”,
defaults: new { id = RouteParameter.Optional }
);

This routing approach has benefits that all routing templates are defined at one common location but for certain URI patterns, it really becomes difficult to support (like nested routing on same controller).

With ASP.NET Web API 2, we can easily support above mentioned URI pattern and others as well. Following shows an example of a URI pattern with attribute routing. URI Pattern –> books/1/authors

[Route("books/{bookId}/authors")]
public IEnumerable<Author> GetAuthorByBook(int bookId) { ..... }

2. CORS – Cross Origin Resource Sharing

Normally, browsers don’t allow making cross-domain calls due to same-origin policy and we know that. So, what exactly is CORS (Cross Origin Resource Sharing)?

CORS is a mechanism that allows a web page to make an AJAX call to a domain other than the domain which actually rendered that specific web page. CORS is compliant with W3C standards and now ASP.NET Web API has support for it in version 2.

3. OWIN (Open Web Interface for .NET) self hosting

ASP.NET Web API 2 comes with a new self hosting package i.e. Microsoft.AspNet.WebApi. OwinSelfHost.   According to http://owin.org/
OWIN defines a standard interface between .NET web servers and web applications. The goal of the OWIN interface is to decouple server and application, encourage the development of simple modules for .NET web development, and, by being an open standard, stimulate the open source ecosystem of .NET web development tools.

So, according to above description, OWIN is an ideal option for self hosting a web application in a process other than IIS process.

There are a number of OWIN implementations like Giacomo, Kayak, Firefly etc. available (some may be partial or outdated) but Katana is the recommended one for Microsoft servers and Web API frameworks.

4. IHttpActionResult

Along with the existing two approaches of creating response from controller action, ASP.NET Web API 2 now supports another way of doing the same. IHttpResponseMessage is basically an interface which acts as a factory forHttpResponseMessage. It’s very powerful because it extensify web api. Using this approach we can compose any specific type of response.

Please follow the link to know how to serve HTML with IHttpActionResult.

5. Web API OData

The Open Data Protocol (OData) is actually a web protocol for querying and updating data. ASP.NET Web API 2 has added support for $expand$select, and $value options for OData. By using these options, we can control the representation that is returned from the server.

  • $expand: Normally, response doesn’t include related entities if we query an OData collection. By using$expand, we can get related entities inline in response.
  • $select: It’s used if we wanted to include subset of properties in response instead of all.
  • $value: It allows to return raw value of the property instead returning in OData format.