Toph - Early Architecture Decisions

by November 9, 2012 12:29 PM

In Another Gig Completes, I mentioned planning to start a new project to help track consulting gigs. Here I introduce you to:

Toph

Project codename named after Toph from the Avatar: The Last Airbender

As I mentioned before, this project is meant not only to help organize my consulting gigs, but also give me a public project and codebase I can point to. I also hope to use the project as blogging fodder. Speaking of which...

Early Architecture Decisions

I've spent the vast majority of my career joining existing projects. There is always that sense of "that's not the way I would have done it". Well, I finally get to do it my way! It was tempting to go crazy with it and implement everything cool I've been reading about recently - whether needed or not, I might add. In the end I decided to go with a pragmatic approach that is much more likely to be a useful example I can point to when talking to developers as I continue consulting.

Visual Studio Projects

I'm still a fan of and will continue to advocate onion architecture (some might say Hexagonal Architecture). One difference you'll find between Toph and what I normally do though, is the lack of an Infrastructure project.

There seems to be a theme going around the blogosphere that is advocating the removal of unnecessary abstractions and part of the theme has been the combining of projects. The idea is that it is perfectly possible to create an architecturally sound solution without using Visual Studio projects to enforce it. In case you're wondering how they "enforce" it, realize that Visual Studio projects won't allow circular references between two projects - whether by directly referencing each other, or indirectly (A - B - C - A would not compile). Therefore if you have a UI and a Core project with UI referencing Core, you couldn't reference UI from Core.  Thus, this usually prevents you from directly doing UI type actions from within Core since you couldn't touch the controllers or view models.

I'm almost always a fan of pragmatic programming. As it turns out, the Infrastructure project never proved that exciting for me as a standalone project. So I just created a namespace within UI called Infrastructure and dumped everything in there. You see, everything usually consider Infrastructure is generally only used during application startup anyway as I'm building up the inversion of control container.

However, I still very much like having my Core separate. It just feels right. So, I decide three projects are all we'll need in this solution

  • Toph (I decided there was no reason to call it Toph.Core)
  • Toph.UI
  • Toph.Tests

Even if I end up adding another project in the future for scheduled tasks (to be run on some application server somewhere), leaving Infrastructure under UI should still be fine. That's because I generally just invoke endpoints in the UI from those background tasks rather than directly dealing with the domain or application's database.

UI

New projects should always be started with the latest and greatest, right? I went with ASP.NET MVC 4 of course. Specifically, I started with the Internet Application project template.

Data Access

That template starts with using a local database and using Entity Framework as its ORM of choice. As expected if you know me, I changed that use SQL Server 2012 Express and NHibernate. To do that...

  1. Delete InitializeSimpleMembershipAttribute. This is the attribute added to AccountController that ensures the database exists and is initialized. There is only one line in there that is needed: WebSecurity.InitializeDatabaseConnection.  I moved that into Application_Start
  2. Delete UsersContext. This is the EF DbContext
  3. Move UserProfile from the Models directory into the domain and kill the EF attributes
  4. Add Fluent NHibernate
  5. Do all the normal NHibernate config and mapping stuff
  6. Change your connection string
  7. Create the database with the single UserProfile table
  8. Run the application

That should do the trick.

Other notables

The only other things I added to the project were Structuremap and my personal code library RobTennyson.Common.

I also stuck with restricting domain access to a Service Layer like I usually do. One difference I thought I'd toss into the mix this time is a bit of CQS goodness (not full blown CQRS, mind you). We'll see how this turns out as the project grows.

Grabbing a copy and playing

If you're interested in playing around with this, but sure you get the code specifically from this commit: 91a19e9f8b

I'll be moving on with the project of course, but at that exact point, the project is still basically just the default template - well, juiced up a bit, but basically still has nothing to do with the real project in it yet.

Happy coding

Tags: , , , ,

What I like About ASP.NET MVC

by March 16, 2010 10:42 AM

I've been asked a lot lately about why one would choose MVC over Web Forms. I'm not so sure about when one should, but I know my default choice is always going to be MVC.

Here are a couple of reasons why

Closer to the metal

With the lack of server controls and postback model, I find myself writing more raw HTML. I like that. Some people won't and that's fine by me. I do.

I meet too many developers who have no idea what the server controls they use actually end up as in the browser. That blows. Some don't even realize the server controls are not real HTML elements. Some don't notice the difference between server and client. I can't remember how many times a developer has asked me if they can call C# from HTML or if they can call javascript from the codebehind. I know the answer to both is "yes" in a round about funky way, but you know what I mean.

Forcing developers closer to the metal is forcing developers to realize what is actually happening. That has to be a good thing.

Forces a more user friendly design

You know how in web forms you can build an entire workflow in a single page using the postbacks? You know, selected index change event on a dropdown, lookup buttons, sorts, filters, wizard controls, tab controls, etc. All these things causing postbacks and firing events and the URL never changing. It's all happening in place due to the magic of web forms and viewstate.

Well, I find that doing anything like that in MVC is hard. And I love that! The result for me is that I end up rethinking my view. I find my putting myself in the shoes of the end user and concentrating more on how to allow them to accomplish the goal as simply as humanly possible. If I really do need richness or dynamic data to accomplish the task, I'm going to do it in an AJAXy way because that's easier than posting back and forth. For the end user, that's a very good thing!

In a nutshell, I tend to focus more on accomplishing goals and less on editing data when I build with MVC.

All the other goodness

Google MVC vs. Web Forms and you'll find a ton of other opinions. I agree with just about every reason you find that favors MVC :). They're all good and whatnot, but the above two are my favorites.

Tags: , , ,

View Responsibility

by November 9, 2008 08:56 PM

On my current side project, I'm writing an ASP.NET MVC application and have been loving it. Something I find myself doing is breaking up a particular view into the main view that gets asked for by a controller and a few sub views. It is these sub views that caused me to ponder the question of responsibility. I wondered if it was the responsibility of the controller to distinguish between the data needed by the main view and the data needed in each sub view, or was it the main view's responsibility to dole out what the sub view needed. I ultimately came to the conclusion that it is the main view's responsibility. Here is my reasoning.

I think a key ability here is to put yourself in the shoes of another.  Or in other words, be able to see something from different perspectives.

For this particular example, I have an action where the user has asked for a particular agenda by date. So I have an AgendaController and a method called Show. The controller gets the appropriate agenda from the domain and selects a view to display it.

From the perspective of the controller: So I've been asked for an agenda. I'll get the agenda and ask a view to display it. I don't care how it gets displayed, just that it does. So I'll pass the agenda object itself to the view.

From the perspective of the view (the one selected by the controller): So I've been asked to display an agenda. I'll make the date of the agenda be the title of the page and put it here. I want the attendance to go right here, but I'll let the "AttendanceView" render that piece so it will look like it does everywhere else. I'll put the blah blah here, and this thingy over there... etc.

You get the idea. The main view is deciding where to put all the pieced of an agenda. It also decides to delegate some of the more complex pieces to other sub views. When it does that, it needs to pass to that sub view what it wants the sub view to display. For example:

<div class="section" title="Attendance">
<% Html.RenderPartial("AttendanceView", ViewData.Model.Voters); %>
</div>

So the controller gave the main view an agenda to render and the main view is taking part of that agenda and passing it off to a sub view to handle. This is where I think this separation belongs. I don't think the sub view should have to share the same model type as the main view, and I don't think the controller should have to put that collection of voters behind a special ViewData key for the sub view. I don't even think the controller should have to know there will be sub views. It's the controller's responsibility to get the domain object, and it's the main view's responsibility to make sure that domain object gets displayed.

Of course, all this is just how I'm feeling about it today. I'm sure I could be persuaded to change my viewpoint fairly easy however.

Happy coding!

Tags: , ,

Dynamic sitemaps with ASP.NET MVC

by October 16, 2008 07:40 PM

I read Jeff Atwood’s post on The Importance of Sitemaps and thought I'd utilize one from the get-go on a site I'm creating for a side project. Seemed simple enough... Well, it didn't turn out a quick 5 minute task like I hoped.

Basically there were two issues. How to return raw content and how to get the encoding right.

How to return raw content was actually pretty easy to find. There's a method on System.Web.Mvc.Controller called Content that accepts a string, the content type, and the encoding. Perfect.

Now, this is probably easy to most, but I've never had to worry about encoding so this one took me a while to get right. First when I tried to serialize my xml document to a string, I ended up with utf-16 in the xml declaration. I knew that's not right because the sitemap specification specifically says it needs to be utf-8.

Help me Google!

The Google gods provided a lot of stuff... and a lot of rabbits to chase and a lot of less than perfect solutions. It was insane how much junk I came across. Many of which provided solutions that basically hacked the phrase "uft-8" into the xml declaration even though the document was physically still utf-16.

In the end I obviously figured it out - or at least, I figured out a solution that works for me and one I feel is somewhat slick. The code:

public ActionResult Sitemap()
{
XNamespace xmlns = "http://www.sitemaps.org/schemas/sitemap/0.9";
var root = new XElement(xmlns + "urlset");
var repository = IoC.Resolve<IRepository<Location>>();
foreach (var location in repository.FindValid())
{
object routeValues =
new
{
state = location.State,
location = location.Name,
controller = "Agenda",
action = "List"
};
root.Add(
new XElement("url",
new XElement("loc", GetUrl(routeValues)),
new XElement("changefreq", "daily")));
}
var memoryStream = new MemoryStream();
using (var writer = new StreamWriter(memoryStream, Encoding.UTF8))
root.Save(writer);
return Content(
Encoding.UTF8.GetString(memoryStream.ToArray()),
"text/xml",
Encoding.UTF8);
}

The main part that took me so long to figure out is the last part where I'm trying to return the XElement I created. The keys ended up being the use of MemoryStream, StreamWriter with the UTF8 argument, and finally using Encoding.UTF8 to get the string to pass to Content().

That's it for the problems that held me up. I would like to add a final note about a problem I'm still having though. Notice the line where I'm calling GetUrl(). That's a utility method I wrote to get a full url from within the controllers. It's easy as pie from within the views, but I haven't found a built in easy way to do it within the controllers - or anywhere else where you don't have an HtmlHelper to play with. Here is that method, but I am still hopeful that an easier built in method exists that I just haven't found yet.

protected string GetUrl(object routeValues)
{
var values = new RouteValueDictionary(routeValues);
var context = new RequestContext(HttpContext, RouteData);
var url = RouteTable.Routes.GetVirtualPath(context, values).VirtualPath;
return new Uri(Request.Url, url).AbsoluteUri;
}

Happy coding!

Tags: ,