2013/10/23

As this was one of those things it took a while to track down I though a quick post would help others trying the same.

I have an up-to-date Jenkins server running builds and I would like to pull a list of failed jobs from the server and display them on a website.
First you need to look up the correct URL to access the list of jobs so after seeing a few posts in blogs and going to the Jenkins Website I worked out it follows this principle.

http{s}//{your Jenkins URL}/api/{xml/json}

If you leave off the xml/json parameter you will get a help page.

I my case I wanted the result in XML as VB.net has good xml integration. So my URL is:

I needed to set up a quick download service for a file stored in Azure Blob Storage. As all examples for this were in C# I thought I’d post a VB.net example for anyone that needed it. The code is documented in the comments. The example also shows sending a HTML email with the URL embedded inside it.

Below is the MVC controller method which generates the URL and sends the email.

I spent most of this weekend, researching different ways to achieve my project. There are certain things that I know I want to do:

Adopt a Three Tier Approach.

Multiple Clients (Including a Website)

A middle service layer that all the clients talk to which can read from the database but not update.

A back end which is the only part of the solution allowed to update the database

The communication between the middle tier and the back end tier will be via the Azure Service bus.

I want the user of the application to be able to log in to the various client using their Windows Account/Google/Facebook ID’s.

With this in mind I was looking into ways to achieve these goals. I was mainly concentrating on what the middle service tier should be.

I wanted something that will make it easy to implement clients on non Microsoft platforms which drew me towards using the new ASP.Net MVC Web API. The downside of this is there is no metadata to describe the service which makes the client much harder to write. After a few discussions with a colleague, they suggested using WCF OData service which should allow making clients easy on the windows side. (Automatic generation of model classes when adding a service reference)

But I’m still open to suggestions from anyone reading this if they think there may be a better way.

The solution structure for the project as it stands now will be:

Tyrannt.Model (Holds the Code First EF Classes)

Tyrannt.Backoffice (Windows Azure Worker Role – The back end tier)

Tyrannt.OData (Web Role – the Middle WCF OData tier)

Tyrannt.Website (First client – will consume the OData service)

I would also like to make use of database migrations that are in Entity Framework 5. Which also brings up another question which it’s been hard to answer. Where is the best place to put the Database context. An easy solution would be to put one in both the Backoffice and OData projects but that means maintaining two separate classes that basically do the same job)

I’ve seen some posts about not having the database context in the same project as the Model classes. I’m trying to work out the best way to do this and still allow database migrations.

Feel free to comment this posts with suggestions ideas or even telling me that I’ve got it all wrong ;-).

As a way of trying to put all the stuff that I am learning together. I’ve come up with a project. I have been attempting to write a game for ages and have decided to make it using all the new Microsoft technologies. (You may have seen some of the preliminary work resulting in blog posts here.)

So this project will be a web based RPG game (With mobile clients to come later hopefully). It will be hosted in Azure and it will make use of Web Roles, Worker roles, SQL Azure, Azure Service Bus/ACS and Azure Storage. It will be written in Visual Basic .Net.

The front page has more details on what is going on and I hope to update the progress regularly here on this blog.

The current site doesn’t do too much as most of the work is going on behind the scenes. But the Codex part will get updates as things progress. In the images section of the codex you can see some of the artwork done by http://www.battleaxegfx.com/
This is one of the images (It will eventually be the Something has gone wrong image)

This project has been going on for a few years using different tools to create hence the collection of artwork and ideas.

2012/11/19

A quick post for those looking to display a formatted XML document on an ASP.net Razor web page. The following code is in the controller and used to create the string to get passed through to the view. This example is based on displaying the information pulled from the Azure Management API as mentioned in previous blogs. The data is stored in a SQL Server database.

2011/07/25

I started to work on a web role to test out experiments with ADO.net code first and ASP.NET MVC 3 with Razor. Out of the box, VS 2010 does not support ASP.net MVC 3 so I created the Azure project, then added a ASP.NET MVC 3 project separately. I then added that MVC project to the Azure project as a web role. Clicked run and all seemed to work fine.

But as with all things Azure, if it works in the developer environment, don’t expect it to automatically work in the cloud.

It didn’t. But I was expecting that. It was a bit hard to track down what the problems were as it only manifested as a web role that never seemed to get started.

Once I had worked out that meant it was missing core components for the web site, I was pleasantly surprised was how easy it was to fix this.

On your MVC 3 project right click the project solution and then select “Add Deployable Dependencies”

Then click the “ASP.NET MVC” and the “ASP.NET Web Pages with Razor syntax” check boxes and click ok.

You will then find a directory added to your project called _bin_deployableAssemblies.

All I did after this was “Deploy” the Azure Project and after waiting for the project to deploy into the cloud, it all started ok and worked.

Then helper methods were created to adjust the page layout and to help with passing information between pages. Also, to help with the application tomb-stoning, the following routines were created in the App.xaml.vb page to store and retrieve information:

Private Sub StoreDetails()
' The PhoneApplicationService stores information while the application is "Active"
Dim phoneAppService As PhoneApplicationService = PhoneApplicationService.Current
' The IsolatedStorageSettings will store informaiton on the phones flash memory to be
' retrieved after the app has shut down and re-started.
Dim settings As IsolatedStorageSettings = IsolatedStorageSettings.ApplicationSettings
' Pull the token GUID from temp storage in the phones memory and write into the
' permanante storage on the phone's flash disk. Only if it exists
Dim token As Guid
If phoneAppService.State.TryGetValue("token", token) = True Then
settings("token") = token
End If
' The same for the remembered username, this will allow the name to be recalled
' after the app has been shut down in any way.
Dim rname As String = ""
If phoneAppService.State.TryGetValue("rememberedUsername", rname) = True Then
settings("rememberedUsername") = rname
End If
' This stores the user group, for the moment, this should only really be done
' if the app is paused to allow another app to run. If the app is exited the
' user will have to log on again anyway.
Dim group As String = ""
If phoneAppService.State.TryGetValue("group", group) = True Then
settings("group") = group
End If
End Sub
Private Sub GetDetails()
' The PhoneApplicationService stores information while the application is "Active"
Dim phoneAppService As PhoneApplicationService = PhoneApplicationService.Current
' The IsolatedStorageSettings will store informaiton on the phones flash memory to be
' retrieved after the app has shut down and re-started.
Dim settings As IsolatedStorageSettings = IsolatedStorageSettings.ApplicationSettings
' The token us used to identify the user without the need for a username and password.
Dim token As Guid
If settings.TryGetValue("token", token) = True Then
phoneAppService.State("token") = token
End If
' if the user has ticked the remember me box, this is the name they used to log on.
Dim rname As String = ""
If settings.TryGetValue("rememberedUsername", rname) = True Then
phoneAppService.State("rememberedUsername") = rname
End If
' this will show if the user is a member of any special user group such as administrator
Dim group As String = ""
If settings.TryGetValue("group", group) = True Then
phoneAppService.State("group") = group
End If
End Sub

Now that this infrastructure is in place we get to the good bit, consuming the login service. The following routines were created to handle the login button click event and code to handle the call back for the login service.

The contents of the username and password from the boxes on the page are used to generate a login type which is defined in the web service but I’ll re-show here:

<DataContract()>
Public Class LoginType
<DataMember()>
Public Property Username() As String
<DataMember()>
Public Property Password() As String
End Class

Then the callback routine to handle the completed login web service call was created and an event handler put into place. Then the ASYNC version of the service (Which is the only one available on Silverlight for Windows Phone) is called and the UI is changed to stop the user from trying to log in twice.
At the server end, the Membership service will attempt to validate the credentials. (A side note: To add a new user, you need to register on the website. Which is all handled automatically if you create an MVC3 website rather than a blank project.)

When the service returns the result of the login, firstly the app checks to see if the e.Error object has been set, this will indicate something went wrong with the service call and for now, it will just display the error message in a message box on the phone (Example of this is a timeout). Next the app will have a look at the returned object which is a TokenType which again is defined in the web service and I’ve shown again below:

<DataContract()>
Public Class TokenType
<DataMember()>
Public Property UserGroup() As String
<DataMember()>
Public Property TokenGUID() As Guid
<DataMember()>
Public Property errorMessage() As String
End Class

The errorMessage property of the TokenType class is used to pass back in the login failed for a username/password error. Basically if errorMessage is “” then everything went OK. If it contains the text “fail” then the username/password combination isn’t valid so the phone app will display that in a message box and reset the display to allow the user to attempt to log on again. If an exception occurred during the login process this is captured by the service and put into the errorMessage property. The phone app will check this and for now display that error message to aid in debugging.

If everything went well, then there should be a GUID in the TokenGUID property which will be used from that point onwards to identify that user. Later I will make every attempt to access the services change this GUID and pass the new one back. I will also add a time out so that the app can get the user to re-login after a period of inactivity has occurred.

If the login was successful we then enable a Logout button and collapse the login button and navigate to the “Member” section of the app using the following command:

2011/03/24

I thought I might as well start with what I’m currently working on outside of work. It’s mainly a learning exercise to (re)teach myself WCF/MVC and learn to develop using windows phone 7.

I decided to start with the back end so created a new VB MVC3 project using Razor. (I’ve not used Razor yet so this is something else new to learn)

The reason I used MVC rather than just hosting a WCF service was to make use of the Membership system that automatically gets created with a new MVC site.

On this new site, I created a services directory and created a service called UserService which will make use of the ASP.net membership provider. I have also created a few Data Contracts that make the passing of data around a lot easier:

Imports System.ServiceModel
Imports System.Runtime.Serialization
<DataContract()>
Public Class LoginType
<DataMember()>
Public Property Username() As String
<DataMember()>
Public Property Password() As String
End Class
<DataContract()>
Public Class IntegerType
<DataMember()>
Public Property IntegerValue() As Integer
<DataMember()>
Public Property ErrorMessage() As String
End Class
<DataContract()>
Public Class TokenType
<DataMember()>
Public Property UserGroup() As IntegerType
<DataMember()>
Public Property TokenGUID() As Guid
<DataMember()>
Public Property errorMessage() As String
End Class
<DataContract()> _
Public Class UserDetailsType
<DataMember()>
Public Property name As String
<DataMember()>
Public Property email As String
<DataMember()>
Public Property lastLogin As Date
<DataMember()>
Public Property errorMessage As String
End Class

These are much smaller since VB10 where you do not need to put in the setter and getter part of properties.

I have also created a table call Players which will contain information about the user which is not already stored in the membership databases and then added a Linq to SQL class so that the service can make use of it:

Linq to SQL Class

Behind this class is the code to interrogate and update the database:

Partial Class TyranntDataContext
#Region "Player"
Public Function GeneratePlayer(ByVal username As String) As Guid
' We first need to access the user ID from the Users table
Dim usr = From user In aspnet_Users
Where user.UserName = username
Select user
' now check to see if the user record exists in the Player Table
If usr.Count <> 1 Then
Return Nothing
End If
Dim q = From player In Players
Where player.userID = usr.Single().UserId
Select player
' if player exists then exit
If q.Count > 0 Then
Return q.Single.guid
End If
' Create the player entry
Dim aPlayer As New Player
aPlayer.userID = usr.Single.UserId
aPlayer.creationDate = DateTime.Now
aPlayer.displayName = usr.Single.UserName
aPlayer.lastLogin = aPlayer.creationDate
' Create a false guid for now, this is only used by the client
aPlayer.guid = System.Guid.NewGuid
Players.InsertOnSubmit(aPlayer)
SubmitChanges()
Return aPlayer.guid
End Function
Public Function GeneratePlayerGuid(ByVal username As String) As Guid
' generate new guid
Dim g As Guid = System.Guid.NewGuid
' find the player record
Dim p = From player In Players
Where player.aspnet_User.UserName = username
Select player
' Update player record with new GUID
p.Single.guid = g
SubmitChanges()
Return g
End Function
Public Function GetPlayerDetails(token As Guid) As UserDetailsType
Dim p = From player In Players
Where player.guid = token
Select player
Dim details As New UserDetailsType
details.name = p.Single.displayName
details.email = p.Single.aspnet_User.aspnet_Membership.Email
details.lastLogin = p.Single.aspnet_User.LastActivityDate
Return details
End Function
Public Sub UpdatePlayerDetails(token As Guid, details As UserDetailsType)
Dim p As Player = GetPlayer(token)
p.displayName = details.name
p.aspnet_User.aspnet_Membership.Email = details.email
SubmitChanges()
End Sub
Private Function GetPlayer(token As Guid) As Player
Dim p = From player In Players
Where player.guid = token
Select player
Return p.Single
End Function
#End Region
End Class

And now the Service contract which allows users to log in, get their details and update part of the details. The Service Contract code is:

Imports System.ServiceModel
' NOTE: You can use the "Rename" command on the context menu to change the interface name "IUserService" in both code and config file together.
<ServiceContract()>
Public Interface IUserService
' User management routines
' Log in to website created user
<OperationContract()>
Function Login(ByVal loginData As LoginType) As TokenType
' Get user details
<OperationContract()>
Function GetUserDetails(token As String) As UserDetailsType
' Update user details
<OperationContract()>
Function UpdateUserDetails(token As String, details As UserDetailsType) As String
End Interface

And now the Bit the does all the work:

' NOTE: You can use the "Rename" command on the context menu to change the class name "UserService" in code, svc and config file together.
Public Class UserService
Implements IUserService
Public Function Login(loginData As LoginType) As TokenType Implements IUserService.Login
Dim token As New TokenType
Try
If Membership.ValidateUser(loginData.Username, loginData.Password) = True Then
' User is valid so now update the player record with GUID
Using db As New TyranntDataContext
' Make sure that the user has a player record
Dim playerGUID As Guid = db.GeneratePlayer(loginData.Username)
If IsNothing(playerGUID) Then
' something went wrong
End If
token.TokenGUID = playerGUID
token.errorMessage = ""
End Using
Else
token.errorMessage = "fail"
End If
Catch ex As Exception
token.errorMessage = ErrorMessage(ex)
End Try
Return token
End Function
Public Function GetUserDetails(token As String) As UserDetailsType Implements IUserService.GetUserDetails
Dim details As New UserDetailsType
Dim playerGUID As Guid = New Guid(token)
Try
Using db As New TyranntDataContext
details = db.GetPlayerDetails(playerGUID)
End Using
Catch ex As Exception
details.errorMessage = ErrorMessage(ex)
End Try
Return details
End Function
Public Function UpdateUserDetails(token As String, details As UserDetailsType) As String Implements IUserService.UpdateUserDetails
Dim playerGUID As Guid = New Guid(token)
Try
Using db As New TyranntDataContext
db.UpdatePlayerDetails(playerGUID, details)
End Using
Catch ex As Exception
Return ErrorMessage(ex)
End Try
Return ""
End Function
Private Function ErrorMessage(ex As Exception) As String
Dim err = ex.Message
If Not IsNothing(ex.InnerException) Then
err += +vbCr + ex.InnerException.Message
End If
Return err
End Function
End Class

For now the idea is if an exception occurs, it displays on the phone to try to help debug the code.

I did not have to code a membership system as this is already handled by asp.net so all I needed the service to do was to call this function:

I have used a token based system so that once the user is logged in, and has received a GUID token, that will be used to identify them from that point onwards. I plan to put an expiry date and time on the token which will make the user have to re-login after a period of inactivity.

I’ve not really gone into using MVC3 yet as I’m mainly working on learning to code on the Windows Phone 7, but I needed something for the phone to connect to.

The code above is in early stages and will most likely change but setting up basic web services is a very easy thing to do in .net

Next entry will show the code for the Windows Phone 7 project.

You may have noticed Tyrannt mentioned above. For anyone interested, it’s a link to this project I’ve been toying with for years 🙂