Browsing:

Category: ASP.NET MVC

ASP.NET 5 getting started from scratch

Let's see how ASP.NET 5 works and discover how we can build a basic website with an API and an Angularjs frontend. Just like we're used to doing with Node.js. Let's see how the Microsoft way compares. Maybe I'm a little late because the current release seems to be 1.0.0.-rc2 on Github. So there's tons of info on the Internet already. And here is my bit as well. 🙂

I will use the Visual Studio Community Edition and I've got a VirtualBox VM running. And let's also host the app in Azure and see how we can collaborate using the Visual Studio Online tools.

First, select File, New, Project and select the Empty ASP.NET 5 template:

aspnet5_1

 

 

 

 

 

 

 

Let's debug and run it immediately!

aspnet5_2

 

 

 

 

Cool! Now where did that came from?

Startup.cs

Startup.cs is the entrypoint for an ASP.NET 5 application. I feel it compares to the app.js or index.js in an Express application which requires all the dependencies needed for the application. It is what the Global.asax was before. There are 2 sections: ConfigureServices and Configure. I think the comments describes their purposes really well:

public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app)
        {

           
            app.UseIISPlatformHandler();
              
            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World!");
            });             
        }

        // Entry point for the application.
        public static void Main(string[] args) => WebApplication.Run(args);
    }

Adding a static page

If we follow along the Express.js workflow, I would now need to add the possibility to add a static file (index.html). And I would need to plug that in to the Startup.cs. And I would need to install the dependencies in a package.json sort of file:

And that is correct. There is a project.json file in the solution and I need to add a dependency to Microsoft.AspNet.StaticFiles. Add it like I did at line 10. (It has intellisense, cool!)

{
  "version": "1.0.0-*",
  "compilationOptions": {
    "emitEntryPoint": true
  },

  "dependencies": {
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final"
  },

  "commands": {
    "web": "Microsoft.AspNet.Server.Kestrel"
  },

  "frameworks": {
    "dnx451": { },
    "dnxcore50": { }
  },

  "exclude": [
    "wwwroot",
    "node_modules"
  ],
  "publishExclude": [
    "**.user",
    "**.vspscc"
  ]
}

Now I can add an index.html file in wwwroot and edit Startup.cs. Delete everything in the Configure method and add 'app.UseStaticFiles();'.

 public void Configure(IApplicationBuilder app)
        {
            app.UseStaticFiles();
        }

Run the app and now this page is served:
aspnet5_3

 

 

 

 

But of course I don't want to type in the URI. I want the web app to server default files.
Then it seems I still need to add middleware to serve the index.html. Add 'app.UseDefaultFiles(); to the Configure method in Startup.cs:

public void Configure(IApplicationBuilder app)
        {
            app.UseDefaultFiles();
            app.UseStaticFiles();
        }

You can find a great explanation here.

So great! That means I can go ahead and add Bootstrap and Angular and that I can write some serious api in C#.

BTW, if you want to know how Microsoft (and the community I must add) has envisioned an ASP.NET 5 web project, please try the MVC web app template.


Getting started with ASP.NET API with MongoLab part 3

This is the sequel to this post
We will be using MongoLab as a backend for our Web Api.

We are using the AddressBook again in this example, but for clarity we're building it from scratch.

Creating the MongoLab database

Head over to MongoLab and create an account!

  • First create a new database. Make sure you choose the free plan. Name the database 'addressbook'.
  • Click to create a new user.
  • Add a new collection (equivalent for a table) named persons.

Please take note of the connectionstring:

2013-11-01 08_12_03-MongoLab_ MongoDB-as-a-Service

Setting up the Web Api project in Visual Studio

Fire up Visual Studio 2013 and hit File -> New -> Project.
Choose Empty ASP.NET Web Application with a Web API and name the project AddressBook.

2013-11-01 08_07_48-New ASP.NET Project - AddressBook

We must install the Mongo Csharp Driver:

Install-Package MongoCsharpDriver

Now open App_Start\WebApiConfig.cs and add json formatting to it (see my previous post why):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace AddressBook
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

//This section you need to add:
            var json = config.Formatters.JsonFormatter;
            json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
            config.Formatters.Remove(config.Formatters.XmlFormatter);
        }
    }
}

Connecting to the MongoLab

Let's not reinvent the wheel if you don't have to. This article is a great introduction to Mongo and C#. I borrowed their MongoConnectionHandler.

using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AddressBook
{
    public class MongoConnectionHandler
    {
        public MongoCollection MongoCollection { get; private set; }

 public MongoConnectionHandler()
        {
            const string connectionString = "mongodb://:@ds031108.mongolab.com:31108/addressbook";
            //const string connectionString = "mongodb://localhost:27017";
            //// Get a thread-safe client object by using a connection string
            var mongoClient = new MongoClient(connectionString);

            //// Get a reference to a server object from the Mongo client object
            var mongoServer = mongoClient.GetServer();

            //// Get a reference to the database object 
            //// from the Mongo server object
            const string databaseName = "persons";
            var db = mongoServer.GetDatabase(databaseName);

            //// Get a reference to the collection object from the Mongo database object
            //// The collection name is the type converted to lowercase + "s"
            MongoCollection = db.GetCollection(typeof(T).Name.ToLower() + "s");
        }
    }
}

The Person class

I want the Person_Id to be the same as the document id, so I can retrieve documents easily. I'm not sure though if this is best practice. But it works.

public class Person 
    {
        public Person()
        {
            Person_Id = ObjectId.GenerateNewId().ToString();
        }

        [BsonId]
        public string Person_Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Phone { get; set; }
        public string Email { get; set; }
        public string Blog { get; set; }
        public string Facebook { get; set; }
        public string Twitter { get; set; }
        public string LinkedIn { get; set; }
        public string Googleplus { get; set; }
    }

And here's the POST method:

public class PersonController : ApiController
    {
        public MongoConnectionHandler collection = new MongoConnectionHandler();

        public HttpResponseMessage Post([FromBody] Person person)
        {
            collection.MongoCollection.Insert(person);
            var response = Request.CreateResponse(HttpStatusCode.Created, person);

          
            string uri = Url.Link("DefaultApi", new { id = person.Person_Id });
            response.Headers.Location = new Uri(uri);
            return response;

        }


    }
      

You can use the API with Fiddler.

2013-11-01 14_33_36-Fiddler Web Debugger

Look at the results it has returned:

2013-11-01 14_35_25-Fiddler Web Debugger

It returned the new URI with the new Id as you can see.

Now let's check MongoLab, and lo and behold:

2013-11-01 14_39_53-MongoLab_ MongoDB-as-a-Service

Here's the remainder of the CRUD methods:

        public IEnumerable Get()
        {
            return collection.MongoCollection.FindAll().AsEnumerable();

        }


        public Person Get(string id) {

            //var query = Query.EQ(p => p.Person_Id, id);
            return collection.MongoCollection.FindOne(Query.EQ("_id", id));

        }

        public void Delete(string id)
        {
            collection.MongoCollection.Remove(Query.EQ("_id", id));

        }

        public HttpResponseMessage Put([FromBody] Person person)
        {
            
            var p = collection.MongoCollection.FindOne(Query.EQ("_id", person.Person_Id));

            if (p != null)
            {
                collection.MongoCollection.Save(person);
            }
           
            return Request.CreateResponse(HttpStatusCode.OK, person);
        }

So, that works.
Next time, let's consume this WebApi with Angularjs.

And here's all the code: here

I have changed 'Person' to 'Contact' in the sourcecode


Uploadify and ASP.NET MVC 3 and scriptData

I'm writing a member registration web application and the customer wants to see a picture with every member. And I wanted to add a progressbar and make it Ajax enabled. There are quite a few upload plugins available and one of them is Uploadify.
Uploadify isn't really Ajax but Flash but hey, it gets the DIV refreshed and that's what it's all about.

I also checked out Telerik but while they have great resources it is a royal pain to set up. You need to add references on all those different places while I like things clean and simple.

So here's how I got Uploadify to work:

Get the software

You can download the latest version here. Oh my, it's more than a year old. Oh well. Let's just get going.
And after that you just read this fantastic article. Done. No just kidding. While this is a great blogpost to get you started, I wanted something extra. I wanted to save the picture in the database. I wanted to rename the uploaded picture and I wanted the name to contain the Id of the person.

Grab the Id (Primary Key) of the record

In the Edit.cshtml just add a hidden label with the Model.Id:

  @Html.HiddenFor(model => model.Id)

Now check out how it renders:

<input id="Id" name="Id" type="hidden" value="5168e-yada-yada" /> 

And we see the name = "Id" and the type is Input, so we need to copy the value with the Uploadify upload.
Uploadify offers the scriptData method for this purpose. In this example I copy the value of the Id DIV to a variable called thisGuid.
This is then being posted to the server as a POST variable ($_POST in php).

 //Upload images with uploadify 
    $("#fotoupload").uploadify({
        'uploader': '/Scripts/uploadify.swf',
        'cancelImg': '/Content/images/cancel.png',
        'buttonText': 'Upload foto',
        'script': '/Person/UploadFile',
        'folder': '/Content/upload',
        'fileDesc': 'Image Files',
        'fileExt': '*.jpg;*.jpeg;*.gif;*.png',
        'scriptData': {'thisGuid': $("input#Id").val() },
        'multi': false,
        'auto': true
    });

Grab the scriptData variable in your controller code

In a former version of Uploadify you could use Request.QueryString["elementName"] but it returns null. Now you can get the value as part of a FormCollection. So you'll need to add the FormCollection to the arguments of your controller upload method. And then you can grab the value with form.Get("elementName").

[HttpPost]
public string UploadFile(HttpPostedFileBase fileData, 
    FormCollection form)
{
   var guid = form.Get("thisGuid");
   var fileName = Server.MapPath("~/Content/upload/" + 
        System.IO.Path.GetFileName(guid + fileData.FileName));
  var person = _repo.getPersonById(guid);
  person.Picture = guid + fileData.FileName;
  _repo.Update(person);
  fileData.SaveAs(fileName);
  return "ok";
}

And there you have it. The picture name is saved in the database with the Id of the person attached.


Castle Windsor ASP.NET MVC 3 Baby Example part 2

This is part 1. The sourcecode is here.
This article is based on this tutorial.

So I created an IStoryTeller interface, with one method that returns a string. GoodMorning.
Very sophisticated, no?
Next, I created 2 classes that implement the IStoryTeller interface. A French and a Dutch. I'm pretty sure you know where this is going:

Now I have to create an installer for the StoryTeller. Here is where I tell Castle Windsor which StoryTeller to implement:

Now I can create the controller and add the IStoryTeller to the constructor:

Run, Forest!

And now if I change the Installer and inject the FrenchStoryTeller I get:

So this is how easy this is.


Castle Windsor and ASP.NET MVC 3 extremely simple example part 1

Castle Windsor is an Inversion of Control Container which has excellent documentation, written by Krzysztof Koźmic. Krzysztof has written a perfect tutorial on ASP.NET MVC 3, which I thought I would follow. And then I found that Castle Windsor is extremely easy and transparent to use. And it has a cool name at that.

What again is Inversion of Control and why ever would I use it?

Suppose you develop a member administration tool and the customer wants to use an MySQL database. But you coded the app with Linq to SQL. Wouldn't it be nice if you could just change your ORM from L2S to EF? Or Nhibernate?
Or, what if you coded your app with an object database, and then later you find that the customer has a DBA who is absolutely against NoSQL?
The same goes for the logging framework. Which one? Log4Net or Elmah?

With IOC you can just pick and choose which framework you plug in. When you start with one choice of a product, you are not bound to it.

It's called Inversion of Control because it's an inverted API. With an API, you use the methods it exposes. With IOC, you let your application choose which API to use. Huh? Yeah. Because when your app spins up, it uses reflection to get all the dependencies you configured within your container. Now, does that make any sense?

A simple example

Here's how the principle works.
In an ASP.NET MVC architecture, there is a Model, a View and a Controller. The Controller sits between the Model and the View, so the Controller would be a good place where we can inject some dependencies. How to inject these dependencies? Well, by their constructor.
The default controllerfactory has a parameterless constructor, so we need to override that, by creating a new class. E.g. WindsorControllerFactory. And we let our controllerfactory inherit from DefaultControllerFactory.
We need to override two methods: ReleaseController (so that he Windsor Controller is released) and getControllerInstance (which returns a Windsor Controller). This bit of plumbing code just provides the MVC runtime with new instances of the controller type for each request and when the request ends, it releases the controller.

Next, we need to register the controllers in to the container with an Installer, like this:

This is how we register types in the container, so there will me more of these classes later.

Now we need to bootstrap this in global.asax:

And then we are ready to roll.

In part 2 I will show how to create some interfaces and inject them in the controller.

Here is the complete example.