No Competitive Differentiators For Our Custom Development Practice

No Competitive Differentiators For Our Custom Development Practice

You probably catch yourself saying to your significant other once or twice a day “So, what can Oakwood do for you?”  We don’t have a unique competitive difference for our custom development practice. We’ve been discussing, arguing, debating, brainstorming, and otherwise dissecting the issue for a long time. During our chats we did make a list of things that SHOULD help us stand apart.  We see so many other companies saying the same things.  But they were not exactly competitive differences at all.

Choices, Choices, Choices.  So, Why Us?

We don’t have a unique competitive difference for our custom development practice. We’ve been discussing, arguing, debating, brainstorming, and otherwise dissecting the issue for a long time. During our chats we did make a list of things that SHOULD help us stand apart.  We see so many other companies saying the same things.  But they were not exactly competitive differences at all.

We Found It

What makes us different is that NO ONE BUT OAKWOOD can say they do ALL of the things on our list.  What other IT consulting firm can offer knowledge, flexibility, accountability, responsiveness, and broad thinking? Clients who have used have good things to say about us. We have earned the Microsoft Software Development Competency and Web Development Competency because we do great work.  Not tooting our horn.  OK, we are.

Earning Your Business

We want an opportunity to talk with you.  Here is what we will cover.

  • We recommend the right solution to our clients that meets their needs and their budget
  • Oakwood Teams work well in your environment
  • Our rates are reasonable and competitive
  • Our developers are extremely knowledgeable; most have Microsoft certifications
  • The teams we deploy are personable, and dedicated to each client
  • We manage projects incredibly well.
  • Daily time checks, and status reporting is done weekly at a minimum.
  • Rock solid project plans

And There's More!

  • Diligent approach to change management procedures. Our project managers are PMI certified PMPs. We run on project management.
  • Enjoy local people, with physical accountability (If you want to look someone in the face and discuss the project the face is right there).
  • A flexible business model.  Fixed fee engagements, milestone-based billing, strategic partnerships – we’re open to figuring out with our clients where these make sense.
  • Our clients know what they are going to get, when they are going to get it, and for what cost.
  • Deliverables are defined, time and scope are managed, and cost is scrutinized every step of the way.
  • Allocation of resources in a way that you do not pay for “thumb twiddling” time. If one project has a lag, the developer switches to another project. The developer stays utilized while you get maximum value for the fees they are paying.
  • Oakwood is not just a development house. There’s an old saying, “when you’re a mason, you build brick doghouses.” When you are just a development shop, the answer to a client question is ALWAYS custom development. At Oakwood, the answer to a question might be a number of other things, like “let’s not re-build it, let’s integrate it to your other system,” or “did you know you could do that in a portal?”

And Even More!

  • Oakwood works with leading edge technologies. We’re cloud developing, web developing, mobile developing, and plain old .NET developing.
  • Our code bases and knowledge objects can be re-used to shorten development time.
  • A consulting firm that does custom development, not a code shop that only does code. Our range of expertise across our consulting organization saves our clients money by providing the opportunity to leverage a variety of technologies into a single solution.
  • Size matters.  Small or large, single-person or multi-person teams.  We can accommodate.
  • Development of long term partnerships.  We still work with clients from our early years – and we are nearly thirty years old!
  • So, what can Oakwood do for you?

What Can Oakwood Do For You?

Taken one at a time, they are all statements that nearly everyone says. Taken as a group, it could just be what makes Oakwood unique.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

The Problem with Infrastructure Operations Managing Applications

The Problem with Infrastructure Operations Managing Applications

For many organizations, infrastructure operations are responsible for running hardware infrastructure associated with the application platform.  The application manager is in charge of managing the application, which includes functional configurations that support all of the underlying business processes.  Most of the time, the application owners are responsible for user management, security, staying on top of the product roadmaps and how they can use their application to drive business value.  In summary, one group provides the “ping”, “power”, “compute” and the other group ensures the application is functional and provides business value.

Murky Waters

Here is where the delineation of responsibility starts to get murky; the end users productivity is being adversely affected because the application is not performing up to standard.  This can take the form of slow logins, search results being slow or not pull back complete results, uploading or retrieving information that takes forever, timeout errors or reports that take forever to run.  A person can only get coffee so many times in a day while they are waiting for their report to run or the document to finish downloading.  The end user now calls the help desk.  The help desk resource begins their troubleshooting steps.  A vast majority of the time performance is looked at strictly as a CPU, RAM, storage latency, or network connectivity issue.  These are the metrics that network administrators deal with on a daily basis.  How do you determine slow with it being such a subjective term?

Baseline Environment

For many situations the performance issue isn’t hardware related, it is related to proper application and database maintenance that hasn’t been performed.  There is value in establishing a baseline of your environment so that you can quantify subjective terms such as “slow”.  This helps determine an end users “slow” vs. another end users “normal” application performance.  Second, maintenance for both the application and database needs to be performed on an on-going basis so minimize the software bloat syndrome.  (I am sure that everyone can relate to the fastest their computer ever worked is the first day that you use it.)  Last, of all, it is important to have monitoring capability to help you ascertain where the bottleneck in performance is originating.  This helps cut down on the “pass-the-trouble-ticket” like a hot potato around the help desk and involving database administrators, infrastructure ops and the application vendor to get the issue resolved.

Infrastructure Operations Conclusion

In my experience, the vast majority of network administrators are not trained to perform this level of maintenance in the application environment.  Most application owners do not have the technical expertise to execute maintenance routines, use application monitoring tools, or interpret the results.  Your options are to either have the application owners or the technical staff receive training on how to execute the maintenance routines, then determine what will be measured, how often it will be measured, and a 360-degree communication plan.  Alternatively, your other option is to hire a service to manage the maintenance function end to end.


Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

Aspect Oriented Programming In MVC

Aspect Oriented Programming In MVC

Sit back and relax.  We are going to get technical.  Ready?  Much like recursion, Aspect Oriented Programming is a programming paradigm for solving problems from a different perspective. The goal of this approach is to create reusable code which solves solution-wide concerns. The end result of investments in Aspect Oriented Programming are usually large dividends due to the opportunity for code reuse. Let’s examine the concept and develop an example.

Aspect Oriented Programming 101

By now most developers have already seen an introduction to MVC and during any introduction, you will quickly begin to see the links between Aspect Oriented Programming and ASP.NET MVC.

If you haven’t had the opportunity to view an intro to MVC I recommend the free introductory training videos on the ASP.NET website.  http://www.asp.net/mvc

The first example you will probably notice is data annotations you add to your data model.

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace MvcApplication1.Models
{
    public class Product
    {
        public int Id { get; set; }

        [Required]
        [StringLength(10)]
        public string Name { get; set; }

        [Required]
        public string Description { get; set; }

        [DisplayName("Price")]
        [Required]
        [RegularExpression(@"^$?d+(.(d{2}))?$")]
        public decimal UnitPrice { get; set; }
    }
}

In this example “[StringLength(10)]” is a data annotation applied as an attribute to the Name property. The really cool thing about these attributes is that they centralize what we know about products and make them more reusable. Now, when we use this model to make a “Create Product” page this attribute will be used. The same attribute will be used on the “Edit Product” page and everywhere else that references the model and as such we only have one place to maintain the proper length for Names of products. Additionally, this information will be sent to the user in the HTML form. When the Razor view engine sees this attribute it will modify the textbox used for editing this data to include the max length validation. Afterwards, the same logic will be used to determine if the object is valid when we inspect the ModelState.IsValid property.

This example showcases the ability to make a decision once and reuse it across the entire project. In other descriptions, you’ll hear that Aspect Oriented Programming is a means to solve “cross-cutting concerns” and this type of solution-wide application of logic is what that statement describes. In addition to data validation, we see here that labels for properties are another cross-cutting concern. Another good example built into MVC is the [Authorize] attribute used to make sure your users have been authenticated before they are allowed to view sections of your site.

Another solution-wide problem developers deal with is performance. Knowing that this is something we care about across the entire project tells us that Aspect Oriented Programming can be a practical approach to this challenge.

public class Log4NetProfileAttribute : ActionFilterAttribute
{
    private Stopwatch swatch;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);

        swatch = Stopwatch.StartNew();
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        swatch.Stop();

        Type controllerType = filterContext.ActionDescriptor.ControllerDescriptor.ControllerType;
        ILog log = LogManager.GetLogger(controllerType);
        log.Info(string.Format("Completed {0} action from {1} controller after {2} seconds",
            filterContext.ActionDescriptor.ActionName,
            filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
            swatch.Elapsed.TotalSeconds));

        base.OnActionExecuted(filterContext);
    }
}

This example consists of two main functional portions a stopwatch from the System.Diagnostics namespace and logging provided by Log4Net.

For a recap of setting up Log4Net see this previous article.

The bulk of the functionality is implemented by the parent class ActionFilterAttribute. As a child of this class, all we need to do is decide what we want to do before a controller action starts and perform our clean up after the controller action completes. Since we’re measuring performance I start up a Stopwatch and then record the elapsed time between the two events. To use this code we can now decorate any controller action in our project with the Log4NetProfileAttribute to receive performance metrics. Additionally, because it uses Log4Net we know that this performance measurement will only be captured whenever we use the INFO logging level.

        [Log4NetProfile]
        public ActionResult Index()
        {
            Random rand = new Random();
            //take a quick nap
            Thread.Sleep(rand.Next(10, 50) * 10);
            return View();
        }

Two things to call out in this example. You will need to use the square brackets, just as we did with the annotations, and you do not include the “Attribute” portion of the class name.

Data validation and user authorization are the two most common areas where Aspect-Oriented Programming can provide a better separation of logic for code reuse but adding it to your toolbox will certainly make some challenges easier to conquer.


Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.


A Mobile Application Brainstorm – Go

A Mobile Application Brainstorm – Go

Do you accept the proposition that every business should have a mobile application?  Part of your acceptance is the acknowledgment that the user community is carrying around hand-sized computers on which they sometimes have telephone conversations.  However, many businesses have not yet made the leap from their particular business model into the mobile application world.

Here, therefore, in no particular order, are a few customer-centric areas that mobile applications could address – geared toward some business types that might not traditionally think of the mobile application play.

Mobile Application | Solutions

  • If you are selling practically anything – from battleships to bubblegum, a catalog of your wares available in a mobile application – even if only to your own sellers – will likely increase sales, customer service ratings, and overall responsiveness.  Own a trade show floor, or own the elevator conversation, when your seller doesn’t have to get out a paper catalog to show what they have to sell.
  • On the mobile catalog front – think about catalogs for parts, services, add-ons – available to installers and/or owners of your product.
  • How about installation manuals and/or repair manuals for those complex items you build?  Can you stand apart from the competition by being the easiest company in your category with which to do business?
  • Find the closest repair shop or service depot.
  • Trade shows a bit part of your business?  How about an app that alerts trade show attendees to the next show/session/demo in your booth?
  • Customer service surveys – on the spot.  Tie this to a QR code to make it super-easy to get instant feedback before a customer leaves the shop, restaurant, or store. (I thought of this while signing the receipt at the auto body shop.)
  • Maintenance reminders, schedules, or appointments for the car, the furnace, the water heater, the boat…
  • In the restaurant business?  How about a mobile app with nutritional information for every item on the menu?  What about ways to ask for them to be made lighter?
  • Remote workforce input – fill out a form, take a picture of what’s been done, annotate a record – good for any business that employs or hires merchandisers, inventory clerks, survey-takers.

Conclusion

Just a few ideas, and not even touching on line-of-business application extensions to your own workforce – real-time order status, customer quoting, inventory queries, etc.  That is an article all on its own.  What ideas do you have?  Any business you’re doing business with – and wishing they had a mobile application because it would make something easier for you?


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.  Let’s have a discussion to learn more about your business needs and goals.


Contact Us

Email

General Questions | Request a Scope of Work
sales@oakwoodsys.com

Charles Windsor | President
cwindsor@oakwoodsys.com
314-824-3000

Phone

♦ 314-824-3000 (St. Louis)

♦ 913-232-4057 (Kansas City)

♦ 800-810-8412 (After Hours)




About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

Azure Development Team Training

Azure Development Team Training

It’s amazing to us the number of customers over the years who told us they couldn’t dare become an Azure Development Team. They are web or mobile developers.  They could not justify investing the time it takes to retrain their developers to build solutions for the Azure platform.  What’s going on here?

Becoming Azure

We are not the fastest developers in the world.  However, we’ve learned over and over again how to deploy a solution to Azure.  As a result, anyone can.

Over the years we have tested this assumption by training many developers. The time commitment was minimal, and so was the actual usage of the new skills.

However, a few customers provided us the ability to truly make Azure a common skill across our development team. This new opportunity provided Oakwood with some very interesting data points. Each of which suggests the same thing: Azure is a pretty easy shift for any development team, both large & small.

The Metrics

Team One Example

25 person team – Total investment: 10.25 hours – Average investment per the developer: 15 minutes – Average investment per architect: 1 hour & 15 minutes.

  • Deployment: 5 initial developers. 1 dev on the team was trained on deployment to Azure.  Took 20 minutes, most of which was spent waiting on deployments so he could see each step. He then trained each new staff members in less than 10 minutes.
  • State, security, & configuration: We hosted one additional architecture session with the senior development team on managing state, integrating with authentication providers, and configuration changes during multi-stage deployments. Total time: 1 hour x 4 team members = 4 hours.
Team Two Example

5 person project – Total investment 3.5 hours – Average investment per the developer: 30 minutes – Average investment per architect: 1 hour & 15 minutes.

  • Following a similar process to the larger team, we were able to share the same kind of training with a significantly smaller team, with similar volumes of investment.

Azure Development Team | Conclusion

If we can learn Azure for developers in less than an hour per developer, there’s no reason you can’t teach developers to support your enterprise-grade Azure projects.  Take our word for it and give it a shot!  Let’s discuss your business needs and work out an hourly rate.


Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

Intelligent Apps Saves On Wasted Service Costs

Intelligent Apps Saves On Wasted Service Costs

Worried about wasted service costs?  Makes sense.  Everyone wants to save money.  It’s the simple things that impact the bottom line, like service costs.  To see this, just follow the paper trail. Understanding how money flows through an organization provides a very clear view into ways to improve the company.  Oakwood pays a lot of attention to these simple but important things.

Saving A Company Some Money | Case Study

One example of this was recently seen in a company that provides services to consumers. This organization like many professional services organization is equal part service provider & service broker. In today’s economy, services are better when companies partner together. However, following the paper trail in this organization demonstrated that 70% of their outbound expenses were going to third-party service providers.

While the services from their third-party partners were seen as mission critical & vital to the success of the organization, they resulted in a cost like any other activity. Where there is cost, there is likely waste and therefore cost reduction.

Service Costs | How We Delivered Success

While building a new interface to manage this customer service management process, our joint team (Developers/BAs, Product Owner, Data Experts) realized that the service assignment process was far from cost-effective. Essentially, the representatives executing this process were focused on completing the task as quickly & efficiently as possible. However, they did not have the data to make quick, efficient decisions that were commonly the most profitable.

With limited investment, relative to the larger project, we tapped some of our Business Intelligence experts to help us construct data structures which evaluated service provider profitability and customer satisfaction ratings. With this information, we simply re-sorted & prioritized the list of service providers available during assignment to maximize the return while minimizing future re-work due to poor service. As a result, the representative lost no functionality & in many cases wouldn’t have even noticed the change in appearance.

Conclusion

However, this approach significantly increased profitability across the board. As a result, it took a significant chunk out of their biggest cost center. Estimates suggest a savings of 30%+ on operational expenses (OpEx). Nice return for resorting a simple list of service providers.

Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

Application Development Lessons from the 90’s

Application Development Lessons from the 90’s

Who is ready to party like it’s 1999 and who remembers anything from the 90’s, especially application development lessons?  What about user experience?  No one was talking about that back then, right?  It’s the simple things that make us better.  Let’s talk about the days of outdated technology, shall we?

Remember Outdated Technology?

20 years ago the cutting firms of the world were standing up the first ERPs at lightening paces. High powered iSeries or AS400 solutions that could solve all of the problems in the world by automating business processes were changing the way our forefathers conducted business. Green screens were changing the world. Cell phones were for drug dealers & power brokers, so they were safely mounted in your BMW.

Memories

Fortunately for me, I didn’t have to write code to run on a server with 8 MB of memory. Or for a screen that only had 2 colors. However, its’ amazing the number of clients who have & still do profitably run on solutions from that era. What’s even more amazing?  The actual impact on profitable that can be added when we make simple changes to those types of solutions.


Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

A Faster Website In 4 Lines Of Code

A Faster Website In 4 Lines Of Code

Want a faster website?  Studies show that slow websites can drive traffic away from your website and directly to your competitors. Performance tweaks are available for every application in varying degrees of ROI. Fortunately, there is an easy way to improve the speed of your ASP.NET website in just 4 lines of code.

A Faster Website

According to Yahoo's 13 Simple Rules for Speeding Up Your Website two of the most important changes you can make to your site are “Gzip Components” and “Add an Expires Header”. While there are numerous changes you can make, these two are the low hanging fruit targeted by the code outlined below.

The urlCompression element will allow IIS to perform Gzip compression of your static components. This is a feature supported by all popular web browsers and allows the web server to send HTML, CSS, and JavaScript content to a web browser in zipped format. The browser will then automatically unzip the file before trying to read the content resulting in reduced bandwidth usage at the cost of a little CPU load involved with doing the compression.
The second block “staticContent” enables the “Expires Headers”. This feature allows you to reduce bandwidth usage by informing web browsers that the content they previously requested is safe to hang on to and will not be changing in the near future. A good example of this is the CSS file associated with your site. The less frequently your CSS changes the more often you want visitors to reuse the CSS file they received from their last visit. There are a couple options to explore. This example uses a set date, of 3/29/2020, the other option is to use a max age configuration which tells the browser to keep the file for a number of days instead of a hard-coded fixed date in the future.

What Does It All Mean?

The caveat to this benefit is that the web browser will not find any changes made to this content until the expiration date has been reached. There are two good ways to address this. If you absolutely need your visitors to see a change today then use a new file name. The new name will not be found in the web browser cache and will be immediately downloaded. The second option is to use a shorter duration cache. This will still reduce the bandwidth load for your application but will ensure that visitors receive the changes in a timely manner.

Both of these configurations should be placed inside of the system.webServer element of the web.config file. Before you give it a try remember this.  Using this configuration enables IIS7 features.  As a result, you will not improve the performance of your website hosted in Cassini Server through Visual Studio. Off you go!  You've got a website to make faster!

Faster Website Conclusion

For additional recommendations grab the YSlow plugin.





About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

The State of the Developer Nation: Mobile Platform Wars

The State of the Developer Nation: Mobile Platform Wars

Who is ready for mobile platform wars?  A report conducted by Vision Mobile features the latest trends in platforms, languages, and tools that app developers are using and how much money they’re making. The report includes responses to an initial survey of more than 10,000 app developers in 137 countries.

Highlights

Android and iOS remain the leaders in the mobile platform war, however there is significant competition between platform providers for developer mind share. The mobile computing market is so much bigger than any before it, that even a tiny share of market represents an installed base that is too large for developers with global ambitions to ignore. Apps with an advertising-supported business models, or social apps depending on network effects target any platform with almost unlimited reach. However, apps on the global scale are now a table stake for new platforms. Platforms that don’t include apps like WhatsApp and Instagram will struggle to gain acceptance on the global level.

The mobile computing market is so much bigger than any before it, that even a tiny share of the market represents an installed base that is too large for developers with global ambitions to ignore. Apps with advertising-supported business models, or social apps depending on network effects target any platform with almost unlimited reach. However, apps on the global scale are now a table stake for new platforms. Platforms that don’t include apps like WhatsApp and Instagram will struggle to gain acceptance on the global level.

Vision Mobile found that the average number of platforms a developer targets has fallen from 2.9 a year ago, to 2.5 in the Q1 report to 2.2 at the time of the survey.

Developer mind share for iOS is down slightly over the last 6 months.  This is not due to fewer developers making the platform their primary target.  Rather, fewer choosing to support both Android and iOS. In most local markets developer mind share is related to platform market share, with a bias towards iOS due to its disproportionate share of the high-end customers – latest official figures imply that the average iOS user is worth 4 Android users in terms of store revenues.

Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

Xamarin Raises $54 Million in Funding For Its Mobile Application Development Tools

Xamarin Raises $54 Million in Funding For Its Mobile Application Development Tools

Xamarin Inc. announced last week that it raised a $54 million Series C round. The funds will be allocated to its mobile application development tool offerings, as well as towards expanding its sales and marketing teams. Great enterprise uptake and a strong partnership with investors, including Charles River Ventures, Floodgate and Ignition Partner, have brought their total funding to nearly $82 million to date. Some industry analysts have suggested it is the largest round ever raised by a mobile app development platform.

Xamarin Game Plan

Xamarin offers cross-platform development software used to build and design mobile apps. It markets its software as quick and easy-to-use with a suite of tools for developing apps for iOS, Android, Mac, and Windows platforms in Visual Studio and C#. Xamarin boasts that its platform is used by 20% of the Fortune 500 companies and deployed across some 120 countries.

Xamarin’s CEO and co-founder Nat Friedman is quoted in a TechCrunch article saying that the company decided to raise a new round this year because the team believes that while the company has seen triple-digit growth every single year since it was founded in 2011, the time to accelerate growth, even more, is now.  As much of our computer usage moves to mobile, Friedman believes the company that builds that best mobile development tools today will be able to offer the best development platform across all platforms in five years or so.

Xamarin: A Compelling Platform

Consider the statistics, over three years, Xamarin has built a community of over 700,000 developers and these developers are delivering to a marketplace that is predicted to grow from almost $1 billion to close to $5 billion by 2017. In addition to Xamarin’s massive business opportunity in the mobile app development industry, Xamarin has strong ties with Salesforce, Samsung, SAP and most notably, Microsoft.

Xamarin formed an official partnership with Microsoft last November and was a prominent figure in the Build conference in April. Xamarin continues work with Microsoft to open source more of its .NET code and other projects in the .NET Foundation.

In addition to its platform for developing mobile apps, the company offers Xamarin Test Cloud, a portal for testing mobile apps. They also debuted Xamarin University, a subscription-based training service offering remote instructor-led training on all aspects of the mobile application development lifecycle, as well as a certification for those who master its mobile app development.


Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

Beginner’s Guide To AngularJS

Beginner’s Guide To AngularJS

Welcome to a Beginner’s Guide To AngularJs.  AngularJS, commonly referred to as simply Angular, is a structural framework, developed by Google, to create highly dynamic web applications. Angular hooks directly into HTML’s syntax to allow your application’s components, making it extremely easy to add Angular to an existing website or template. Using data binding and dependency injection, Angular is able to drastically eliminate the amount of code you need to write and maintain. On top of that, Angular comes with the ability to perform both Unit Tests, and End-To-End Tests to help ensure every aspect of your application is running as intended.

What Is AngularJS

This blog post will cover the basics of getting an Angular application up and running, along with several other current “best practices”.

This blog post is written with respect to the Angular 1.3.x branch:

https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js

Table of Contents


Your First Creation

First things first. Before we can build anything using Angular, we’ll need to create a new HTML file and import AngularJS. To do this, we’re going to utilize Google’s CDN.

%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a28%

Now that we have laid the foundation by including the Angular javascript file we can start making our application

Extending the HTML

Earlier, I mentioned AngularJS hooks into a web page simply by extending the HTML. It does this by utilizing directives. At a high level, directives are markers on a DOM element that tells Angular’s HTML compiler to attach a specified behavior to that DOM element. Angular comes with a number of built-in directives, like ngBind, ngModel, and ngClass. In addition, if Angular doesn’t already contain a directive to do what you want, you can easily create your own to accomplish your goals.
One thing you’ll notice is all of these directives began with two letters, ng. Angular uses this with their built-in directives to help users differentiate between the built-in directives and user created ones.

For our first application we’ll be using three directives:

  1. ngApp – This defines the namespace in which your application will interact. It is possible to have multiple ngApp declarations on a single page all executing within their own scope.
  2. ngModel – This directive binds data from HTML controls, such as input fields, checkboxes, and text areas into the application’s scope.
  3. ngBind – The last directive we’ll be using continuously updates the text inside an element with data from your application.

Next, we will need to do is declare where on our page the application will reside. You can attach this to any HTML element on the page, such as a

element, the element, or even the element. For our example, we’re going to attach it to a newly created

element inside the as follows:

You will have noticed the attribute we added to the div element wasn’t ngApp, but instead data-ng-app. Angular follows a design pattern where directives are all camelCase meaning the first word is all lower case, there are no spaces, and every word thereafter starts with a capital letter), while the associated HTML convention is all lower case with words separated by hyphens. The reason we added data- in front and hyphenated ng-app is because we want to keep our document HTML5 valid. You can remove the data- and simply have ng-app=””, and your angular will work just fine.

Now that we have declared the space our application will control, let’s have it do something!

Within our newly created application division, let’s insert the following code:

This snippet of code has two components. First, we added an input field and assigned it the attribute data-ng-model=”FirstName”. This tells Angular that whatever a user types into this input field need to be bound to the variable FirstName within the application’s scope. We’ll go into the application scope later on.

The second thing we added was the data-ng-bind=”FirstName” attribute onto a paragraph, element. This attribute tells Angular that we want the contents of this paragraph element to display whatever data is currently bound to the FirstName variable inside the application’s scope.

Putting it all Together

Your current HTML document should look something like this:

%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a29%

Open this file in your browser of choice and simply type your first name into the input field. You’ll notice the web page updates in real time with whatever you type.

(Internet Explorer Users: You might receive a notification that Internet Explorer restricted this web page from running scripts or ActiveX controls. If so, all you need to do is click the ‘Allow blocked content’ button to enable javascript).

Congratulations, you’ve made your first Angular application!


Expressions

As we saw in the last example when using the ngBind directive we need to attach it directly to an HTML element. By doing so, Angular constantly replaces that elements contents with the bound variable’s value. What if, instead of simply displaying your first name, we wanted to preface it with “Hello, ” greeting? We would need to modify our code to be:

Hello

While this will work, you can imagine that once you have a lot of different dynamic elements your code will become extremely cluttered. As an alternative Angular provides Expressions. Expressions work similar to ngBind by allowing the developer to place javascript code directly onto the page.

Below, is an example of using Expressions instead of ngBind to display our dynamic data.

Hello {{FirstName}}

Notice that in Angular, Expressions are denoted by wrapping your javascript code in double curly-braces. Also, the HTML quotation marks are no longer needed since FirstName is now a true variable. It’s as simple as that.

Notice in my previous statement I said Expressions are able to wrap javascript code. We can also place logical components, like mathematical expressions.

{{2+3}}

In addition to simple inline statements, we can also execute functions inside of an Expression. While we aren’t quite ready to create functions, they will come along shortly.


Controllers

Up to this point, we really haven’t done much coding and our application is fairly simple. This is about to change. We’re going to look into creating our own ngController to help us add some complexity and functionality to our application.

The first thing we’re going to do is create our modules. You’ll remember from the first page I hinted about how Angular supports a very compartmentalized structure allowing for a high degree of code re-usability and maintainability. Angular does this by using what it calls Modules.

Declaring our Application

To get started we need to declare our application inside of our HTML. You do this by adding the name of your application inside the ng-app=”” section. For this example, let’s call our application myApp; so our resulting HTML would look like this:

Now that we have declared our application, we need to actually create it within our javascript. When you start building real applications, you will want to create individual javascript files for each module. However, for the sake of this example we are going to keep everything inside a single document.

To create our myApp application inside Angular, we need to add the following block of javascript code:

var app = angular.module("myApp", []);

Seems easy enough, right? Well, there are several important things going on here, despite the small amount of code we added.
First, you will notice we are declaring a variable, app, to be our binding point for the application module. This comes in handy later on when creating things like controllers, services, or even our own directives.
Second, you will notice the angular.module() function takes two parameters: the name of the module, in this case, “myApp”, and an array which is used for injecting services into our application. For now, we will leave it empty and we won’t worry about it.

Registering a Controller

Now that we have declared our application and bound it to a variable, the next step is to actually create a controller module. To do so, we use our app variable as such:

var app = angular.module("myApp", []);
app.controller("myController", function($scope) {

});

If you are not familiar with typical object notation, this might look a little weird. What we just did is tell Angular that we wanted to attach a controller to our myApp module. To create a controller, we need to pass two parameters. The first parameter is the controller’s name; in our case “myController“. We are also passing a second parameter, and that is a function of a parameter called $scope. Remember earlier when I mentioned an application’s scope? Well, this is it! When we create a controller for an application Angular is passing that applications $scope variable into the controller for us to manipulate. It’s also important to remember that earlier I said ngModel was binding FirstName to our scope. When the application initialized, Angular created a variable on the $scope object named FirstName that stores that information.

Now that we’ve registered our controller, we need to place it inside the HTML so that angular knows what region it has control over. Similarly to how we declared our application, we need to attach the ngController directive to an element inside our page.

When all is said and done, our resulting HTML document should look like this:

%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a210%%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a211%
Hello, {{FirstName}}

Now that we have laid the application/controller foundation we can really start making our application dynamic!


Manipulating the $scope

Once we have successfully declared our application and attached a controller to be used we can begin adding properties to the $scope to be used inside the HTML.

Dot Notation

Let’s start by adding a variable to the $scope object. We can accomplish this by modifying the contents of our controller function.

If you recall, objects in javascript can have properties added to them at any point using the dot notation. For example, let’s say we want a Person object in javascript. To create this object, all we need to do is the following:

var Person = {};

This will initialize the variable Person to be an empty object. Now, lets add the properties FirstName and LastName to the person object. We can do that in two different ways. The first would define those properties when we initialize the Person object:

var Person = {
    FirstName: "",
    LastName: ""
};

Alternatively, we can use the dot notation to add those properties to an already created Person object:

var Person = {};
Person.FirstName = "";
Person.LastName = "";

Angular utilizes this second (dot notation) method to dynamically create variables as needed. That’s how our early code worked — there was an implicit $scope variable that dynamically gained the property FirstName when we attached it to the input field using the ngModel directive.

Adding Our First Variable

Using what we just learned about how Angular utilizes Dot Notation to dynamically create properties on the $scope variable, let’s add a property called FirstName to the $scope:

app.controller("myController", function($scope) {
    $scope.FirstName = "Brandon";
});

Place the updated controller inside your HTML page and see what happens.

If you’re curious how this might be applicable, place the following code in a new HTML document and open it in your browser:

%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a212%%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a213%
{{WidgetCount}} widgets would cost you ${{WidgetCount * WidgetPrice}}

Pretty cool, eh!

Creating a Function

Variables are nice and all, but the real programming power comes from functions. Functions are attached to the $scope in a very similar manner to variables. Start off by updating our HTML document to ask for the visitor’s First and Last name.

Hello, {{FirstName}} {{LastName}}

Now that we have that in place, instead of displaying the visitor’s name using two expressions, lets create a function that does it for us.

Inside of our Controller module, attach a function named CombineName to our $scope variable

app.controller("myController", function($scope) {
	$scope.CombineName = function(){
	
	};
});

We just told Angular that whenever the CombineName $scope variable is called, it needs to execute this function. Define this function to return a string of FirstName LastName:

app.controller("myController", function($scope) {
	$scope.FirstName = "";
	$scope.LastName = "";
	$scope.CombineName = function(){
		return $scope.FirstName + " " + $scope.LastName;
	};
});

Finally, now that our function is set up and ready to rock, lets update our HTML page to call this function:

Hello, {{CombineName()}}

Our resulting HTML document should look like this:

%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a214%%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a215%

Hello, {{CombineName()}}


Directives, Directives, Directives

While Angular comes with a large number of built-in Directives, for this course I’m only going to cover a few of the most commonly used ones. To see a full list of directives, visit Angular’s Directive API page.

ngShow (https://docs.angularjs.org/api/ng/directive/ngShow)

In our previous examples, the document looks a little funny saying “Hello, ” before a visitor enters their name. The ngShow directive will allow us to dynamically control when elements are displayed depending if its value is true (show the element) or false (hide the element). Now having ng-show=”true” or ng-show=”false” isn’t that dynamic, or even that useful. Instead, when using the ngShow directive we can give it an expression to evaluate.

Let’s update our HTML page to hide the “Hello,” text if the contents of FirstName is empty.

Hello, {{CombineName()}}

By adding this directive onto the page, we are directing the browser to show the text “Hello” only when the $scope variable FirstName is not empty (i.e. has a length greater than 0). Now, as soon as the visitor starts typing their first name you’ll notice the paragraph element switches from hidden to shown.

ngInit (https://docs.angularjs.org/api/ng/directive/ngInit)
The ngInit directive allows us to execute an expression the first time that element is initialized. Typically, this directive is placed on the same element as the ngController to call some function. Let’s say you were creating an application that displayed information about employees at a company such as their name, hire date, department, etc… To get this information, we need to pass Angular the Employee’s ID in order to an out database and extract the information. While we won’t be doing the data gathering methods (that will come later) we will stub it in for this example.

%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a216%%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a217%
{{FirstName}}
{{LastName}}
{{Department}}

This example we had ngInit call a function attached to the $scope named GetEmployeeData() and pass the parameter employeeID to be used inside that function. Pretty easy, right?

ngClick (https://docs.angularjs.org/api/ng/directive/ngClick)

The ngClick directive is very similar to javascript’s onClick method. When attached to an HTML element and, that element is clicked the directive will execute whatever expression it currently holds. Let’s modify our HTML document to include a button that, when clicked will say “Hello” to the visitor.

First, we need to add an element to the page that we want users to click. For this, let’s use a simple button.

The next thing we need to do is attach the ngClick directive to our button. For now, let’s assume when clicked we’re going to call a function on the $scope called Greeting().

Next, let’s create the $scope function to execute when that button is clicked.

$scope.Greeting = function(){
    alert("Hello " + $scope.FirstName + " " + $scope.LastName);
};

ngRepeat (https://docs.angularjs.org/api/ng/directive/ngRepeat)

The final directive I’m going to touch on is the ngRepeat directive. Angular’s ngRepeat directive allows us to display repeatable data, such as a list, without knowing anything more than the property of each list item. Let’s take this course for example. We have a number of students registered for this course, each of which has a First Name and the Last Name. If we want to display this list of information to a visitor, we could use the ngRepeat directive to cycle through a list of students and output each of their names.

To start, we will need a class list (or array) of students:

var Person1 = {
    "FirstName": "John",
    "LastName": "Doe"
};
var Person2 = {
    "FirstName": "Jane",
    "LastName": "Row",
};
var Person3 = {
    "FirstName": "Joe",
    "LastName": "Smith"
};
$scope.People = [
    Person1,
    Person2,
    Person3
];

Place that javascript code into your controller.

Next, we need to display that information on our page. Let’s use a table to display that information:

First NameLast Name
{{item.FirstName}}{{item.LastName}}

There are a few interesting components to the ngRepeat directive worth discussing in more detail.

First, notice the expression we are using here. The ngRepeat directive works similarly to a for each loop. In this code, we are saying “For each item inside of the People $scope variable, execute the following code”. What follows is whatever HTML we need, including the element containing the ngRepeat attribute.

	{{item.FirstName}}
	{{item.LastName}}

Second, notice how the expression was “item in People“. To Angular, we’re defining the variable item as the temporary holder for the current object. On the first pass through, item will be {“FirstName”: “John”,”LastName”: “Doe”}, and on the second pass through item will be {“FirstName”: “Jane”,”LastName”: “Row”}, and on the third and final pass through item will be {“FirstName”: “Joe”,”LastName”: “Smith”}. This explains why we had to have {{item.FirstName}} instead of {{FirstName}} in each expression.


The $http Service

While we have made a fairly decent Angular application thus far, everybody knows that real applications need to be able to send and receive data with different web services (like APIs). This allows your application to truly be dynamic. To accomplish that, we’ll utilize one of Angular’s built-in services, the $http service.

Services

Before we dive into the $http service we should first talk about Services in general. Similarly to directives, Angular comes with a number of built-in services we can use right out of the box. Just like directives, if Angular doesn’t already have a service that accomplishes what you are looking to do, you can always make your own. Angular Services are basically substitutable objects that can be injected into controllers. This follows Angular’s pattern of trying to keep things modular. If multiple controllers are going to need access to the same object, containing the same information and functions, you need to create a Service and inject that service into your controllers. The really neat thing about Services is they can hold information outside of the controller scope. This means you can have multiple controllers on a single page talking to each other by passing data through a Service.

The $digest Cycle

If you’ve previously used AJAX (Asynchronous JavaScript + XML) you might be curious why we can’t just use that and instead need to use Angular’s $http service. Angular has a unique way of watching the DOM as well as it’s internal application scope. If you change a variable, either on the DOM or inside the application’s $scope using javascript outside of Angular it won’t register that anything changed and won’t update. There are a few ways around that, like forcing the update cycle to run or wrapping your javascript with Angular services, but whenever possible you want to keep non-Angular frameworks out of your code.

The following image might seem a little complex right now, but it will be good to keep it in the back of your mind. This shows the basic cycle Angular has when dealing with displaying data on the DOM and knowing when to run it’s internal $digest cycle.
AngularJS $digest cycle
Angular attaches itself to the DOM’s native event loop. The event queue is a process your browser is constantly executing which runs javascript functions. When the visitor’s page loads, Angular adds a function onto the event queue to execute it’s $apply function. Angular’s $apply(function) executes checking all binding and updating the $scope and DOM as needed, and then adds itself to the end of the event queue to be run again. This means Angular’s $apply() function is being executed a number of times per second (unless you clutter the event queue with outside javascript).

Implementing Angular’s $http Service

First, let’s start by creating a new application using the pattern we have been working with:

%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a218%%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a219%

If you take a look at inside our javascript where we declare our application controller MyController you’ll notice the function has our $scope parameter. This is where we are going to place the reference to the $http service. By doing this, we’re telling Angular we want it to resolve the reference using the $http service object. Angular does this by using dependency injection.

app.controller("myController", function($scope, $http) {
    		
});

We are now ready to start utilizing the $http service object inside our controller. $http service is able to perform all HTTP methods (Get, Post, Put, Delete, etc…). For this example, we’re going to use the .get method built into the $http service.

Looking at the Angular API documentation for the .get method, we can see it has two parameters. The first is the URL which is required, and the second is an optional config parameter. The optional config parameter is used to do things like modifying the method headers, or in the case of .post (Links to an external site.) send data. For now, we’re going to use a simple Get with no configuration options. W3Schools.com has a public endpoint available for us to use at https://www.w3schools.com/js/js_json_sql.asp. If you visit the link, you’ll notice the data being displayed is in a JSON format. JSON is the default format the $http methods expect back. If you’re connecting to a web service that returns XML, you can declare that the response data is of XML format inside the optional config parameter.

To retrieve the JSON data from https://www.w3schools.com/js/js_json_sql.asp we’ll need to add the following code inside our controller:

$http.get("https://www.w3schools.com/js/js_json_sql.asp");

Now that we have that code inside our controller, we’re still missing a few key additions to consume that JSON data and do something with it.

To start things off, we’ll need to attach a success condition to the .get request.

app.controller("myController", function($scope, $http) {
	$http.get("https://www.w3schools.com/js/js_json_sql.asp")
		 .success(function(data)
		 {
			$scope.Customers = data;
		});
});

By doing so, we’re telling Angular that once .get has successfully received it’s information execute this function by passing the received information into the data parameter. We then take that data variable and place it’s information into the $scope object’s Customers property.

We could stop here. We’ve successfully retrieved the information from our URL endpoint and saved it into our $scope. However, what happens when the web service is However, what happens when the web service not accessible (e.g. due to maintenance)? Instead of a successful response, our .get method will have an error response and the visitor will have no idea why the information was never retrieved.

To inform the visitor that there was an error retrieving the information, we’re going to attach an error condition to the .get request.

app.controller("myController", function($scope, $http) {
	$http.get("https://www.w3schools.com/js/js_json_sql.asp")
		 .success(function(data)
		 {
			$scope.Customers = data;
		 })
		 .error(function(data)
		 {
			alert('There was an error getting the Customers list');
		 });
});

Now that we have the customer data attached to our $scope we can use the ngRepeat directive from earlier to output a list of customers onto our page.

%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a220%%MINIFYHTML4acbe603c97dad68f81b4d5644b2f4a221%

Customers

NameCityCountry
{{customer.Name}}{{customer.City}}{{customer.Country}}

Conclusion

And there you have it. You now possess enough tools to begin transforming a static website into a highly dynamic one.


Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

Using External Authentication Providers to Secure Your Apps

Using External Authentication Providers to Secure Your Apps

A struggle that many web developers face is how to secure your apps. While it is pretty straightforward to develop some sort of username/password authentication, it becomes much more complex when considering self-service account maintenance. Things like registering, changing or resetting passwords, maintaining names, email addresses, etc. can all ramp up the complexity.

Secure Your Apps

I realize the Microsoft MVC template delivered with Visual Studio implements quite a bit of this functionality when creating a new MVC application. But, depending upon the industry or the level of security required, there is another way to authenticate users while pushing the responsibility of user maintenance onto other developers, external authentication providers.

What I’ve Learned

By using the OAuthWebSecurity class in the Microsoft.Web.WebPages.OAuth namespace, applications can leverage OAuth providers such as Facebook, Live, and Twitter or OpenID providers like Google and Yahoo to authenticate users. Adding providers is relatively simple, requiring some configuration on the provider and registering the provider in the application.

Getting Started

First, start with an empty MVC application. Once created, manage NuGet packages and add the Microsoft WebPages OAuth library (Now, here is the first gotcha. There is a disconnect in Visual Studio 2013 between the MVC and OAuth libraries. Running the application will result in a version mismatch exception. While in NuGet, go to Updates and update all packages. This should fix the mismatch).

Create an AuthConfig class. This class is responsible for configuring/registering each of the external authentication providers.

using Microsoft.Web.WebPages.OAuth;

namespace OAuthDemo
{
    public static class AuthConfig
    {
        public static void RegisterAuth()
        {
            OAuthWebSecurity.RegisterMicrosoftClient(
                clientId: "",
                clientSecret: "");

            OAuthWebSecurity.RegisterTwitterClient(
                consumerKey: "",
                consumerSecret: "");

            OAuthWebSecurity.RegisterFacebookClient(
                appId: "",
                appSecret: "");

            OAuthWebSecurity.RegisterGoogleClient();
        }
    }
}

and register the authorizations in the Application_Start event of the Global.asax.

            AuthConfig.RegisterAuth();

Each external provider requires registering the application. For each provider except Google, this will also set the id, secret combination necessary to configure in the application. Microsoft provides some guidance on how to configure each provider here.

Configuring each provider does have some gotchas. For instance, Microsoft Live does not allow http://localhost as a redirect URL. This article provides a workaround to that limitation. However, Google does not recognize the workaround as a valid domain, so testing is somewhat of an adventure.

Once registered, the external providers can be iterated to allow users to log in using their preferred (or required) provider.

In the Controller:

        public ActionResult Index() {
            return View(OAuthWebSecurity.RegisteredClientData);
        }

In the View:

                @model ICollection
                @foreach (AuthenticationClientData p in Model)
                {
                    
                }

It is a simple matter then of requesting authentication with the selected provider, verifying the results and finally authorizing the user. It is important to note that each provider returns a slightly different data set, though each provides a unique identifier for the user. Also, the user’s email address is returned in the dataset except when using Microsoft Live. Returning the email address from Live requires elevated privileges that most users are unwilling to grant.

                OAuthWebSecurity.RequestAuthentication(Provider, ReturnUrl);
            AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new {ReturnUrl = returnUrl}));
            if (!result.IsSuccessful) {
                return RedirectToAction("ExternalLoginFailure");
            }

            // User is new, ask for their desired membership name
            ViewBag.ProviderDisplayName = OAuthWebSecurity.GetOAuthClientData(result.Provider).DisplayName;
            ViewBag.ReturnUrl = returnUrl;
            return View("ExternalLoginConfirmation", new RegisterExternalLoginModel {UserName = result.UserName, ExternalLoginData = loginData});

Conclusion

Microsoft Azure also provides an access control namespace service which provides very similar functionality from the cloud. But, that is a topic for another day …


Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.