NOTE: instructions below are for MonoDevelop 2.6 Beta 2 - built on 2011-04-06 03:37:58+0000
Create a new ASP.NET Web Application in MonoDevelop:
- From the menu, select: File → New → Solution…
- Expand C#.
- Select ASP.NET → Web Application.
- Enter a name for the ASP.NET project that will be created in the solution in Name:.
- Change the root location for the solution in Location:, if desired.
- Change the name of the root solution in Solution Name:, if desired.
The Results – I
What you have after executing the new ASP.NET Web Application project wizard is a solution containing one ASP.NET Web Application project. In the default project view in MonoDevelop, you'll find the following items:
- Default.aspx – This is the default web form rendered and presented in the browser when http://<server>:<port>/ is accessed.
- Default.aspx.cs – This C# file contains the developer-created common code and event handlers which can be used to affect the processing of the form.
- Default.aspx.designer.cs – This C# file contains the IDE-generated code for the page.
- Global.asax – This file contains the basic information which is available to the entire application.
- Global.asax.cs – This C# file contains methods and event handlers for the entire application. These include event handlers for: application initialization, application termination, session handling, error handling, and request handling.
- web.config – This file contains the primary configuration for the application when deployed to a server. A secondary set of configuration options can be found in the server's Machine.config file.
If you go out to the location where you created the solution/project, you will also find a few other files:
- /<solution name>/<solution name>.sln – This file contains configuration information for the entire "workspace" of projects.
- /<solution name>/<solution name>.userprefs – This file is generated by MonoDevelop and contains information specific to the user of the MonoDevelop application. The consensus is that this file should not be included in source-control.
- /<solution name>/<project name>/<project name>.csproj – This file contains configuration information for the particular project.
- /<solution name>/<project name>/<project name>.pidb – This binary file contains meta-data generated by MonoDevelop. The consensus is also that this file should not be included in source-control.
Setting Up the Web Service
Since I'm only really interested in exposing a web service using this project, I felt that I really don't need the Default.aspx.* or Global.asax.* files as they are currently not doing anything for the project. I deleted all five of the files.
Create a new ASP.NET Web Service file in MonoDevelop:
- In the Solution pad, right-click your project and select: Add → New File…
- Select ASP.NET → Web Service.
- Enter a name for the file that will be created in the project in Name:.
The Results – II
After the ASP.NET web service wizard has completed, you'll find a new asmx file in your project. This file will contain the basic WebService directive, some using statements (System and System.Web.Services), a namespace, and a class definition.
Exposing a Method in the Web Service
Next, you'll want to create a method that you want to expose as a method on your web service. Add the WebMethod attribute to it. Your asmx file will now look something like this:
When you run this project, you can view a simple front-end for the service at http://localhost:8080/<web service file name>.asmx. This web form is created at runtime by the ASP.NET container.
What? No code-behind?
While it is normally a good practice to separate a view from the code which contains its logic, as in an aspx file, there is really no reason to do so in an asmx file as there is no visual component which must be separated from the code.
I'm setting out to learn .NET and get some experience creating a non-trivial project. Microsoft does provide Express (free, Windows-only) editions of the Visual Studio application in a few flavors as well as basic version of IIS with ASP.NET and SQL Server. But, since my current personal development environment is a MacBook Pro (OSX 10.6.7), getting started with development on .NET can actually cost money (mostly due to the Windows tax). The primary development tool for .NET developers on non-Windows systems seems to be Mono with MonoDevelop.
The latest stable release of Mono (2.10.1) supports much of the functionality of the .NET 4.0 platform and some portions of Microsoft's extended .NET eco-system: F#, IronRuby, IronPython, ASP.NET MVC(1, 2, and portions of 3).
The latest beta build of MonoDevelop (2.6 beta 2) provides a lot of support for developing applications using C# and the rest of the CLR.
I'll be using these in the coming months to do some experiments in the creation of a blogging engine in .NET. As part of proving that I can work in the .NET world. You can see the results of my experiments on my github page.
Mono also provides two other interesting projects:
I spend a large part of my time developing web services, so I spend a lot of my time testing web services. One of the major tools I have in my toolbelt for automating web service tests is SoapUI. SoapUI does a lot of things, and even does a lot of things which I don't need, but it does the things I need very well. Today, I was trying to set up some testing for the security on my current project. As I was setting up the test request and pointing SoapUI at the appropriate endpoints with invalid http basic authorization credentials, I realized that there was no straight forward way to assert that the http response code was 401 (unauthorized) or 403 (forbidden). I did some digging, and found that you could create a Script Assertion (using Groovy) in the SOAP Test Step and use the pre-defined variable, messageExchange, to examine contents and statistics for the test step.
Asserting that a SOAP request with no credentials was responded to with a 401
Asserting that a SOAP request with invalid credentials was responded to with a 403
The Script Assertion also has access to two other pre-defined variables: context and log. context contains methods which allow you to examine the request and response programmatically and log, well I haven't had to use yet. These are posts for another day.
One of my tasks for the current iteration was to add security constraints to the J2EE web service that we are currently developing. This is the easy part. Simply define the appropriate security-constraint, login-config, and security-role elements in the project's web.xml.
From the above, you can see that I defined an expected role, AUTHORIZED_USER, an expected realm for http basic authentication, APP, and a set of resources, / and /*, which can only be accessed through SSL by a user who is a member of the AUTHORIZED_USER role. This is the easy part and should work for most application servers which are worth their salt.
This project is already using the jetty-maven-plugin to run a test instance of the application. I thought it would be a good idea to make sure that the security on the localhost instance for testing would work in the same manner as the WebSphere server to which the application is to be deployed. This would help me to ensure that I, as a lazy programmer, would not have to change the functional tests (SoapUI) between localhost and dev.
By default, the jetty instance created by executing mvn jetty:run-war does not include a user realm for defining users and groups, a login service for handling attempted logins, or even the capability for handling SSL connections. In order to bring these components into the localhost instance, I had to make some changes to the configuration of my project's jetty-maven-plugin. First, the changes for enabling the user realm and login service.
pom.xml (version 1)
Using the keytool-maven-plugin for generating a certificate for SSL
In order to enable server authentication, the Jetty instance needs to have access to a server certificate to be sent out in the SSL handshake. I did some investigation and found that there was a plugin, keytool-maven-plugin, which would allow you to automate self-signed certificate generation in the maven execution. I modified the project's pom as follows:>
pom.xml (version 2)
Adding SSL support to Jetty
Now, we have a way for the client to authenticate itself, a realm for assigning that client's roles, and a keystore. We just need to tell Jetty how to expose an SSL port to the world.
pom.xml (version 3)
A big thank-you to mrhaki and his article Configure Maven Jetty Plugin for SSL Communication for the assist.