http://weblogs.asp.net/scottgu/archive/2007/10/14/asp-net-mvc-framework.aspx
Monthly Archives: October 2007
Going to DevTeach? Party with Palermo location announced!
It’s official! Party with Palermo is the official opening party of DevTeach Vancouver. We’ve worked with the conference organizers to bring you a blockbuster party at Steamworks.
Book your calendars for Monday, November 26, 2007. The party kicks of after the pre-con, so finish your session, grab a bite to eat and then come out for the party for music, fun, drinks, and more.
RSVP at the party website, www.partywithpalermo.com
For future announcements, subscribe to the party feed or the feed via email.
Please add this badge to your website or blog to promote the event:
If you’d like to be an event sponsor, find out more here.
Linq to Xml – querying an RSS feed
Linq (and all its flavors) will come out with .Net 3.5 and Visual Studio 2008. Along with the Xml support are classes such as XDocument, XElement, XAttribute, etc. What’s interesting about XElement in particular is that it allows us to load some Xml from many sources and query into it. Depending on your experience with XPath, an Xml Linq query may be easier to write AND read.
Let’s look at a sample Linq to Xml query. I’m going to use my blog’s RSS feed, http://feeds.feedburner.com/jeffreypalermo.
Let’s start simple. We’ll read in the Xml from the RSS feed and enumerate through all the posts (or "items" in the RSS world).
XElement rssFeed = XElement.Load(@"http://feeds.feedburner.com/jeffreypalermo");
var items = from item in rssFeed.Elements("channel").Elements("item")
select item;
Console.WriteLine(items.Count());
foreach (object o in items)
{
Console.WriteLine(o);
}
Note that we are merely reading in the feed into an XElement and then selecting all item nodes from the document.
That’s pretty interesting that we can filter to only the "item" nodes that quickly, but what if I want to find the posts with the author of "Jeffrey Palermo" (never mind that this is my feed, but imagine it was a composite feed).
XNamespace dc = "http://purl.org/dc/elements/1.1/";
XElement rssFeed = XElement.Load(@"http://feeds.feedburner.com/jeffreypalermo");
var items = from item in rssFeed.Elements("channel").Elements("item")
where item.Element(dc + "creator").Value == "Jeffrey Palermo"
select item;
Console.WriteLine(items.Count());
foreach (object o in items)
{
Console.WriteLine(o);
}
I gave this example to illustrate how to use the XNamespace class to help filter in nodes that declare a namespace prefix such as "dc:creator" in an RSS feed. Note the "where" clause in my Linq query.
Let’s go further and filter down to just the posts that contain the term "altnetconf" (or choose another term to search for)
XNamespace dc = "http://purl.org/dc/elements/1.1/";
XElement rssFeed = XElement.Load(@"http://feeds.feedburner.com/jeffreypalermo");
var items = from item in rssFeed.Elements("channel").Elements("item")
where item.Element(dc + "creator").Value == "Jeffrey Palermo"
&& item.Element("description").Value.Contains("altnetconf")
select item;
Console.WriteLine(items.Count());
foreach (object o in items)
{
Console.WriteLine(o);
}
Now we’ve seen how the where clause functions. Let’s shape the data now. I’ll drop the where clause for simplicity, and I want to grab my feed and put a title and abstract into a collection for use in my application. I’ll use an anonymous type to help me do that.
XElement rssFeed = XElement.Load(@"http://feeds.feedburner.com/jeffreypalermo");
var items = from item in rssFeed.Elements("channel").Elements("item")
select new { Title = item.Element("title").Value,
Abstract = item.Element("description").Value.Substring(0, 100) }
;
Console.WriteLine(items.Count());
foreach (object o in items)
{
Console.WriteLine(o);
}
Here, I have created an anonymous type with a Title and Abstract. Now that I have the information in object form, I can work with it. I would not want to work with Xml throughout my application, but only at the edges. I prefer to pull in the information and get it into my domain model as quickly as possible because objects are easier to work with that raw Xml.
I’m not finished yet because my type doesn’t have a name, so there is no way I can pass my IEnumberable<whateverthetypeis> to another part of my application. I need to hydrate one of my domain objects so I can work with my abstracts.
I’m going to use this class:
public class PostAbstract
{
private string _title;
private string _abstract;
public string Title
{
get { return _title; }
set { _title = value; }
}
public string Abstract
{
get { return _abstract; }
set { _abstract = value; }
}
}
I’ll have the results of my Xml query create a set of PostAbstracts, and then I can work with them.
XElement rssFeed = XElement.Load(@"http://feeds.feedburner.com/jeffreypalermo");
IEnumerable<PostAbstract> items = from item in rssFeed.Elements("channel").Elements("item")
select new PostAbstract { Title = item.Element("title").Value,
Abstract = item.Element("description").Value.Substring(0, 100) }
;
Console.WriteLine(items.Count());
foreach (PostAbstract anAbstract in items)
{
Console.WriteLine("{0} - {1}", anAbstract.Title, anAbstract.Abstract);
}
Note that I merely gave my type a name, PostAbstract. I used object initializers to set the properties, and now I have a set of objects I can work with to accomplish my purpose.
If you enjoyed this article, subscribe to my feed: http://feeds.feedburner.com/jeffreypalermo
When will YOU plan an AltNetConf?
First, go read Bil Simser’s post about planning an AltNetConf in your area, and then go read Martin Fowler’s post about his take on Alt.Net.
Ok. if you came back, read on:
Everyone can be a community leader. You don’t need permission. There is no one who is going to tell you “no”. You just have to decide for yourself that you are going to do something great in your own area.
I’ll close with a direct quote from Bil Simser:
On the heels of the first one in Austin there are a few good ideas that you could use when you’re building your own AltNetConf:
- Keep the size manageable. I think the 100 person limit was great for the Austin one. This also helps you locate a place for it.
- Self-organizing
agenda. Rather than pre-canned agenda of topics, the first day/night of
the conference is the time to collaborate and drill out what people are
passionate about. What bugs people, what do they want to talk about.
This is an agenda driven by both speaker and speakee (as I would
consider everyone a speaker for each session, with someone keeping the
conversation on topic rather than coffee-talk, much like a Scrum Master
does during the daily standups) - Nothing but .NET. This isn’t
Alt.JAVA so the conversations follow building on Microsoft platforms
using the most appropriate tool, technology, and technique that makes
sense for the problem at hand. - Don’t turn it into a vendor
fest. While it may be Microsoft related, I think the last thing an
AltNetConf needs is “Brought to you by [insert .NET vendor product
here]”. True, it should be free and things cost these days, but there
are too many ideas that spiral out of control and become product
showcases rather than guys and girls talking about software development. - Follow the OpenSpace approach to organization and flow. Just resonates on the ideas above.
Summary of Domain Specific Languages (DSL) meeting at ALT.NET conference – from David Diehl
David Diehl doesn’t have a blog, but he asked me to post his notes from the Domain-specific language session at AltNetConf. Read below
What is a DSL?
“A thin veneer over top of an API” (Martin Fowler)
Two types of DSL
Internal — Domain language implemented as a fluent interface in a “standard” language (erg., Ruby, C#, Python)
External — Domain language that is parsed / compiled as its own language
The Key Attributes of DSLs (Fowler)
1. Should read like a language. This is a subjective criteria, but it should have a type of grammar.
2. Business users (domain users) should be able to make sense of it. In other words, it uses the “ubiquitous language” (Evans) of the domain.
Some Examples of DSLs
1. XAML is a DSL for designers
2. NHibernate is a DSL for O/R mapping and persistence
Possible Pitfalls When Using a DSL
1. The language can become too general very easily. The language must be very specific. Some would say NAnt has drifted too far from its original intent.
2. It can become hard to handle errors and debug a DSL. When this becomes difficult, it’s a warning sign that the language is becoming too generic.
3. If you are using an external DSL, you must test the layer between the DSL and the existing API thoroughly.
How to capture a DSL (Fowler). The two approaches
1. Build the DSL over top of an existing domain model and API
2. Capture the DSL with the requirements. Martin noted an experience where a developer had a laptop and was doing some DSL development right with the business expert.
What method should you choose?
No clear winner. It depends on what one you are most comfortable with.
Recommended Tools
1. ANTLr is the tool recommended at the moment for parsing and creating external DSLs.
2. Scott Guthrie recommended the use of debug visualizers to help with debugging and error handling.
altnetconf links and buzz
http://del.icio.us/search/?fr=del_icio_us&p=altnetconf&type=all
The above is a link to the altnetconf tag in del.icio.us. I’ve been tagging every blog post I find related, and so have others. Here’s a quick list:
-
altnetconf – Alt.Net kicks off with clarification of “What is Alt.Net”
-
Flickr: altnetconf pool
-
altnetconf: Blogs, Photos, Videos and more on Technorati
-
Flickr: Photos tagged with altnetconf
-
altnetconf – Google Code
-
altnetconf – Google Code
-
AltNetConf Day2 – Agile and MVC Goodness – Rod Paddock
-
altnetconf – Scott Guthrie announces ASP.NET MVC framework at Alt.Net Conf – Jeffrey Palermo [MVP]
-
altnetconf – Scott Guthrie announces ASP.NET MVC framework at Alt.Net Conf – Jeffrey Palermo [MVP]
-
ALT.NET – Home
-
ALT.Net first day impressions
-
There and Back Again : ALT.NET Conference, Day 2 – Taking the Good With the Bad
-
Random thoughts on Open Spaces fishbowl
-
Luke Breuer: Webpage Index
-
Another reason for Rhino Mocks Generic Constraint
-
Ryno’s Blog: More Blog Sites
-
Summary and opinions regarding the Behaviour Driven Design session
-
ALT .NET Open Space Conference
-
MVP Framework for ASP.NET
altnetconf – AltNetConf is over, here’s the follow-on information
Wow! AltNetConf was great. There were so many positive people from all over the country and some international folks. Of course, having Scott Guthrie and Martin Fowler there didn’t hurt either.
The discussion continues. Join the altnetconf Yahoo group here: http://tech.groups.yahoo.com/group/altnetconf/
Pictures! Join the altnetconf Flickr group here: http://www.flickr.com/groups/altnetconf
Also, for you attendees, please tag your content altnetconf so that the content is easy to find. We worked through a lot of great issues over the weekend, and it would be great to be able to share that information easily.
Photo of me talking with Rod Paddock (chief editor of Code Magazine).
[tags: altnetconf]
altnetconf – Scott Guthrie announces ASP.NET MVC framework at Alt.Net Conf
asp.net mvc framework
Note: Much more MVC information coming. Subscribe to my feed: http://feeds.feedburner.com/jeffreypalermo Subscribe to email feed.
Scott Guthrie proposed a topic at the Alt.Net Conference today, and the topic was an overview of the MVC Framework his team is working on. His topic is actually the first timeslot of the conference at 9:30am tomorrow morning. Just about everyone showed interest, so I wouldn’t be surprised to see most of the folks just listening.
Scott and I had supper after the opening, and I received a personal demo of the prototype. First, here are some of the goals:
- Natively support TDD model for controllers.
- Provide ASPX (without viewstate or postbacks) as a view engine
- Provide a hook for other view engines from MonoRail, etc.
- Support IoC containers for controller creation and DI on the controllers
- Provide complete control over URLs and navigation
- Be pluggable throughout
- Separation of concerns
- Integrate nicely within ASP.NET
- Support static as well as dynamic languages
I’m sure I missed some of the goals, and more people will blog their takeaways since this all is public information.
The first question might be: Is webforms going away? Do I have to rewrite my web applications? Some people might wish, but no. Both models will be supported and even be supported within the same web application. I, for one, after seeing this, think it is very good, and my company will be recommending it to our clients.
We might get a public CTP by the end of the year, and it will be released in a similar fashion as ASP.NET AJAX was, as an add-on after the Visual Studio 2008 release some time next year.
URLs
The default URL scheme will look something like this:
/<RouteName>/<Action>/<Param1>/<Param2>
where RouteName is configured to map to SomeController. Multiple routes can map to the same controller for the purpose of providing more URLs (think SEO).
The developer can completely override the URL processing also by providing an implementation of an interface.
Controllers
Controllers will inherit from a base class by default, but it doesn’t hinder unit testing, and it’s not even required. I’ll probably use the option of implementing the IController interface instead and creating a controller factory to support controller creation using my IoC container of choice (currently StructureMap). In this manner, I implement an interface with one method that accepts IHttpContext (yep, we have an interface now), and RouteData, a simple DTO that includes the action and parameters for the web request (parsed from the URL scheme you are using).
Views
Like I said before, NVelocity, Brail, etc can be bolted on as view engines, and ASPX is provided as a view engine (the only thing that has been changed is that the code-behind will inherit from ViewPage as opposed to the current Page). Controllers can either using IViewEngine (I think that’s the name) to request a view by name (key) or using a helper method on the optional controller base class RenderView(string, viewData). The default model uses a DTO for the objects passed to the view, so it is similar to MonoRail’s property bag except it’s a strongly-typed DTO (using generics for that), so when you rename stuff with Resharper, you don’t have to worry about any string literals lying around.
My impressions
I first saw the early prototype in March of this year, and I was encouraged. I was able to give some early feedback, which has already been encorporated into the product. I’m not one to promote a Microsoft offering just because it’s there (I have never recommended the use of MSTest over NUnit, for instance), but I will say this: As soon as I can get my hands on a build, I will be building something with it. I am very encouraged by this, and I think they are going in the right direction. While they have chosen a model to use with demos, they have broken down the walls. Interfaces abound, and none of it is sealed. I will start by swapping out the controller factory so I can get my IoC container in the mix, but it’s easy to do. For testing, there is no coupling of the controller. The views are decoupled. The httpcontext is decoupled with the new IHttpContext interface. The actions are simple public methods with an attribute attached to them ([ControllerAction], I think).
Isn’t it just like MonoRail?
Someone using MonoRail for more serious project than me can comment more intelligently, but here goes. MonoRail is MVC. This is MVC, so yes, it’s very similar but different. This gives us a controller that executes before a view ever comes into play, and it simplifies ASPX as a view engine by getting rid of viewstate and server-side postbacks with the event lifecycle. That’s about it. MonoRail is much more. MonoRail has tight integration with Windsor, ActiveRecord and several view engines. MonoRail is more than just the MVC part. I wouldn’t be surprised if MonoRail were refactored to take advantage of the ASP.NET MVC HttpHandler just as a means to reduce the codebase a bit. I think it would be a very easy move, and it would probably encourage MonoRail adoption (even beyond its current popularity).
[tags: altnetconf, asp.net mvc]
altnetconf – Alt.Net kicks off with clarification of “What is Alt.Net”
Alt.Net kicked off this evening with the setting of the agenda. We have so many topics, there are going to be a LOT of great discussions. I feel privileged to be a part of a conference that is potentially shaping the .Net community. . . and I enjoyed meeting Martin Fowler for the first time. We have plenty of space for all the discussions thanks to St. Edward’s University in Austin. St. Ed’s has been very supportive of the developer community here.
First and foremost, we established that Alt.Net does NOT mean anti-Microsoft. Earlier, I gave some values and principles as an attempt to clarify somewhat how _I_ think of Alt.Net.
Alt.Net does not mean tools. Alt.Net is a way of thinking, a value system. At its core, we want to be passionate about our craft. We want to use the best tools for the job (we know those tools change every 2.5 years). When a new tool that is better comes along, we will happily drop current tools (and that’s a good thing). We want to keep an open mind about how to write software because we know there is no _one true way_.
Another key point is that Alt.Net encourages the challenging of every assumption we make. Assumptions can turn to habits, so we must be aware when context changes and rechallenge our assumptions to ensure we are working in the best way.
We intentionally limited the defining discussion because that discussion will be going on all weekend. Alt.Net is a very positive message, and everyone at the conference is looking for ways to improve the .Net community, not whine about it. The opening was very positive and upbeat. There are a lot of smart folks in the room, and I look forward to learning from them over this weekend.
In short, we don’t have a definition. Sorry folks. We have 100 or so people at AltNetConf, and we have almost as many definitions, but we all share a passion to develop better software and educate others in the same. While there are some folks using completely different platforms, most are using .Net and want to continue building on .Net, so Alt.Net does not mean finding an alternative to .Net. On the contrary, I want to learn the best ways to fully leverage the platform.
For all bloggers, we are tagging content as “altnetconf” to help make this stuff more searchable.
[tags: altnetconf, agile, alt.net]
Generic constraint for Rhino Mocks – make unit tests more readable
I use Rhino Mocks, and I encourage you to do the same. When unit testing, sometimes its necessary to interrogate an object that was passed to a dependency.
Consider the following test code:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
1: [Test]
2: public void ShouldSaveObjectWithAllInformation()
3: {
4: string firstName = "Jeffrey";
5: string lastName = "Palermo";
6:
7: MockRepository mocks = new MockRepository();
8: IPersonRepository personRepository = (IPersonRepository) mocks.CreateMock(typeof (IPersonRepository));
9:
10: personRepository.SavePerson(null);
11: GenericConstraint personConstraint = new GenericConstraint();
12: LastCall.On(personRepository).Constraints(personConstraint);
13:
14: mocks.ReplayAll();
15:
16: PersonController controller = new PersonController(personRepository);
17: controller.PersonFirstName = "Jeffrey";
18: controller.PersonLastName = "Palermo";
19: controller.Save();
20:
21: mocks.VerifyAll();
22:
23: Person person = (Person) personConstraint.GetParameterObject();
24: Assert.That(person.FirstName, Is.EqualTo(firstName));
25: Assert.That(person.LastName, Is.EqualTo(lastName));
26: }
This is a case where we have a class that takes information, creates an object and sends it to a dependency. The dependency doesn’t need to return what was just passed to it, but in our unit test, we need to be able to assert that the object was created correctly before being passed to the dependency. This is not an edge case. I run into this scenario quite often.
What did I do to keep my test readable? I created a Rhino Mocks constraint class that captures the argument passed to a dependency. Later, I can write plain old asserts that verify the state of the object. Here is the class:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
1: public class GenericConstraint : AbstractConstraint
2: {
3: object _theObject;
4:
5: public override bool Eval(object obj)
6: {
7: _theObject = obj;
8: return true;
9: }
10:
11: public object GetParameterObject()
12: {
13: return _theObject;
14: }
15:
16: public override string Message
17: {
18: get { return ""; }
19: }
20: }
I prefer this over even the built-in constraints Rhino Mocks provides because I find the Assert syntax to be more familiar with more programmers than the in-line constraint syntax. Notice on line 12 of the test listing that I’m assigning this constraint to the mocked call to IPersonRepository. This allows me to come back later on line 23 and pull the object for interrogation. Once I have a reference to the object that was passed to my dependency, I can write the appropriate asserts.
Feel free to use this constraint class or comment with how you’ve handled this situation.