Monday, August 15, 2011

Small update

Still breathing, still wrapping things up.  Trying to do a fair amount of testing before unleashing the first site on the world.  Next up: uploaded image validation testing.

With all of my previous EF4 issues, I had a lot of duplicate table rows, which really screwed up some of my model structure, so I've spent the last little bit rebuilding my test db and EF model.  Should be ready to go tomorrow.

Something to add to my "Microsoft should focus on the following when trying to get people in on the ground floor" list:

A crash course in core OOP patterns.  Factories, IoC, Repositories, various data patterns, etc.  The kinds of things a MVC coder will undoubtedly run across early on.  Just an idea.

Monday, July 18, 2011

Objects in mirror are closer than they appear

What's this?  A non-bitchy, non-whining, perhaps even HAPPY blog post?!

Yup.

I'm inching closer to the finish line.  A bunch of not hard, tedious stuff (tightening up the graphics on level 5, and whatnot), and one non-trivial design decision (nothing major, just trying to figure out how to address something in a somewhat intelligent way), and it's done.

I've actually learned a lot during this process.  I'm anxious to see how things flow with a fresh project, to see if I've learned what I think I've learned.

Tuesday, June 28, 2011

Our long national nightmare is over

Creating/editing my complex EF4 entity graph with a many-to-many relationship finally works the way I intended.  I... I'm not sure what to say.  More shock than happiness right now.

My biggest issue, as you know, was figuring out what the ObjectContext expected of me.  When to attach/detach/add/remove... it's a frustrating dance to engage in, and at times even complex.  A lot of that fumbling stemmed from my inexperience, which is part of the reason why I'm doing this.  I need to get this right, even if I go kicking and screaming.

The other problem is myself (cue: "I could've told you that").  I get tunnel vision, and I'm stubborn as a mule.  That's not a good combination.

Unsurprisingly, the solution was simple, so simple it's embarrassing.  That's something else I do - write convoluted code, and then whittle it down (again, while kicking and screaming) until the solution is a mere handful of lines.  I guess my brain needs to contort itself for a bit before discovering the right way to go.

A special shout out to Julie Lerman, who humored me both on Stack Overflow and Twitter, and who must surely think I'm some sort of psycho stalker.  Thank you.

So... maybe I can get this thing finished this month.  Whodathunkit?

Friday, June 24, 2011

AutoMapper? More like DeciptiMapper

Well, it looks like AutoMapper has a bug in its AfterMap and BeforeMap methods.  Specifically, if you try to use a loop in order to populate the destination object with values derived from the source object, the Map methods themselves are invoked multiple times.  Not cool when dealing with EF4.  I now have several copies of the same Platforms in my test db.  Yay four extra XBox 360, PS3, and PC entities!

As always, a link to SO: http://stackoverflow.com/questions/6460177/extra-iterations-in-a-foreach-in-an-automapper-map/6473451#6473451

Thursday, June 23, 2011

Same as it ever was reprise

More 'fun' with Entity Framework 4, ASP.NET MVC, and many-to-many relationships.

Change tracking in EF4 is actually pretty good.  The problem comes when you're trying to edit an existing Entity with data from an outside source.  Then, the whole thing goes to shit, and you're forced trying to figure out exactly what to do all while the system is throwing vague exceptions telling you you can't do what you want to do.  And, naturally, all of the demos/tutorials I've seen are based on moronic demoware that anyone could figure out.  No real world examples anywhere to see.

I don't feel like blowing up the project structure I have simply because EF4 is acting like a bitch.  Part of this project is so I can learn how to do things the right, professional, ideal way, which is what I'm going to do.

Even if it kills me.

Like always, a link to SO: http://stackoverflow.com/questions/6460071/ef4-problems-w-mvc-entitykey-many-to-many-relationships-etc-what-fundamental

Thursday, June 2, 2011

I'll give YOU an ObjectContext! *angry fist shake*

Here's what's going on with my ASP.NET MVC 2/Entity Framework 4.0 project:

I have two VS projects in my solution.  One is the domain, which contains my EF entities and repositories, and the other is the web UI, which contains the MVC bits and pieces.  I'm trying to do things the right way, so my web UI can have references to the domain, but the domain shouldn't have references to the UI.  My repositories are injected into my controllers via Ninject interface injection.  Simple enough.

I had my Create/Edit Game code working, but it was ugly.  I was partially binding directly to a Game entity, but for the complex stuff I was passing along other form data directly to the repo's Save method, wherein I would do what I needed to do to build/rebuild the many-to-many relationship between Games and their respective Platforms.  It worked, but it was ugly, especially since it required one of my repository interfaces (remember, they're injected into the controllers by the interface, so I use that API in the controllers rather than casting them as their concrete selves) to accept extra data in order to do its job.  That seems like a layer/coupling issue to my novice senses.  I just want a nice, clean public void SaveGame(Game game) method.  So, it was both a cosmetic and design decision to bind incoming data to a DTO, and then map it to the Game entity.

The problem is now the many-to-many relationship I'm trying to (re)build between Games and Platforms is throwing ObjectContext exceptions at me, and I'm not sure why.  I'm getting two kinds of exceptions - one is telling me that my Platform entities cannot be Added to my Game because they exist in different ObjectContexts.  The other I'll explain a little later.  I've tried 'registering' a new, null Game object by Attach/AddObject-ing it to my context like so:

Controller:
Game game = new Game();
_gameRepository.RegisterGame(game);

Repository:
public void RegisterGame(Game game)
{
    _siteDB.Games.Attach(game);
}

I tried all the variants in the register method: _siteDB.Attach(game), _siteDB.Games.Attach(game), _siteDB.Games.AddObject(game).  All gave me the same exception.

When I tried Adding the Platforms by just their EntityKeys (game.Platforms.Add(new Platform { EntityKey = src.EntityKey })), I would get an exception informing me that the entities I was trying to save had EntityKeys which already matched those within the ObjectContextManager, most likely because the Platforms already exist.

So, at this point, I'm not 100% sure how to move forward.  I don't understand why my old version of attaching the entity to the context and manipulating the Platform data originally worked, but now its not.  It's almost as though my Attach/AddObject invocations are losing scope because I'm doing it through a repository interface.  Odd, and frustrating.

Code and more detail here: http://stackoverflow.com/questions/6195167/problems-trying-to-attach-a-new-ef4-entity-to-objectcontext-while-its-entity-coll

Tuesday, May 31, 2011

Well, I'll be a master of EF4 when this is all said and done

I apparently have fallen prey for a classic Entity Framework 'gotcha'.  Null ObjectContext and needing to play with EntityKeys.  Not quite sure how to do it with an EntityCollection, so, like always, I posted the details on Stack Overflow: http://stackoverflow.com/questions/6195167/problems-trying-to-attach-a-new-ef4-entity-to-objectcontext-while-its-entity-coll

Monday, May 23, 2011

Different day, same problem, maybe some hope

I'm still facing the same problem which plagued me last week.  My form is somewhat complex - several textboxes, one text area, two dropdowns, more than ten checkboxes, one textarea, and two file upload inputs.  The edit model which I'm trying to bind all of that stuff to does not map 1:1 with my entity.  I've been looking at AutoMapper as a possible solution, but since my entity is actually an entity map (it contains a many-to-many relationship, which is what the checkboxes are for), there's some extra complexity which is tripping me up.

My plan, right now, is to give AutoMapper access to my repository so it can build the map.  Hopefully, all I'll need to do when I call Save() is attach the newly mapped object to the context and save it.

Of course, there are still the files to save, but that seems a bit more straightforward than the entity map.

Link to my Stack Overflow question: http://stackoverflow.com/questions/6062914/asp-net-mvc-2-and-automapper-dissecting-and-mapping-uploaded-file-info-with-aut

Thursday, May 19, 2011

SoC: Yeah, you know me!

Wondering if there's a graceful way to handle something that, on the surface, would break SoC.  Short version: I have an edit model I want to pass into my repo's validator, but I don't want the repo to have a reference to the edit model, as the repo is part of the domain and the model is with the UI.  Details and code here: http://stackoverflow.com/questions/6062914/asp-net-mvc-design-question-input-edit-model-reference-in-the-domain

So, nerd collective, how badly have I designed my code?

Tuesday, May 17, 2011

Still alive (insert witty Portal reference HERE)

Yeah, so I'm still alive.  Some distractions have come up, so my progress has come to a screeching halt.  Thankfully, it looks like most of what I have left to do before release is the small, tedious stuff.  Fleshing out a controller here, making some views there.  Nothing I can't handle, and certainly nothing complicated.  All of that was taken care of (with the customary amount of kicking and screaming on my end) at the beginning.  My little 404 detour was the last of the hard stuff, and something I didn't anticipate.

Like any good nerd, I already have a growing list of things to put in version 2 of the site, including:
  • Revamped layout
  • Redesigned database structure (nothing too drastic, just some refinement to make my queries simpler)
  • Full text search with Lucene.NET
  • Comment system
  • Online forums?
My immediate concern is handling file uploads.  It seems simple enough (I'm basing what I'm trying to do off a tutorial by Phil Haack: http://haacked.com/archive/2010/07/16/uploading-files-with-aspnetmvc.aspx), at least on the surface.  Hopefully the new edit model I'm almost done writing will work as expected.  If not, I can work around it until I can find a better solution to implement in version 2.

In any event, it looks like mostly smooth sailing until I actually upload this sucker to the live environment.  I'm sure that will be an experience.

Friday, April 29, 2011

Set facepalm levels to 'Picard'

Well, I figured out my problem.  Naturally, it was me being an idiot.  I forgot to change my strongly typed view to accept a view model instead of a string.  The way the exception appeared, I thought it was telling me that RouteData.Values was throwing it.  Turns out it was the internal dictionary of the view itself.


SO link: http://stackoverflow.com/questions/5808554/asp-net-mvc-2-route-errors-problems-when-using-cottsaks-solution/5838686#5838686

Wednesday, April 27, 2011

Same as it ever was

So, I've made a bit of progress with my 404 implementation, but I'm encountering a NotImplementedException that I'm not sure how to solve.

I'm trying to implement the solution found here: http://stackoverflow.com/questions/619895/how-can-i-properly-handle-404s-in-asp-net-mvc/2577095#2577095  The difference being, I'm using vanilla Ninject 2.0 as my DI container.

Details of my current problem: http://stackoverflow.com/questions/5808554/asp-net-mvc-2-route-errors-problems-when-using-cottsaks-solution

RequestContext is telling me it needs a string somewhere in its internal dictionary.  I don't see where I'm not supplying it a string.

Tuesday, April 26, 2011

Crisis averted

Turns out my SQLEXPRESS service was turned off for some reason.  No idea why, as it's set to automatically run.  Sorry for jumping the gun.

If it's not one thing, it's another

No attempt at a witty title tonight.  I made some minor changes in attempt to get my bad route handling squared away, and now all of a sudden I'm getting an EntityException, specifically that the underlying provider failed on Open.

FFFFFFFFFFFFFFFFFFUUUUUUUUUUUUUUUUUUUUUU

I haven't touched my domain code in days - neither my repositories nor my connection string - and, yes, I'm sure my connection string is in my Web.config.  It was working just last Friday, and the only changes I've made tonight have been removing [HandleError] from an action method and using named parameters when calling a view.  That's it.

As always, more detail on SO: http://stackoverflow.com/questions/5798047/ef4-entityexception-the-underlying-provider-failed-on-open

Monday, April 25, 2011

And now something to lighten the mood

Since I was diagnosed with diabetes at Christmas, this has become one of my favorite things:

While my keyboard gently weeps

As I wait for the ability to offer a bounty on my route error/500/404 problem on Stack Overflow, I figured I might as well write a letter to Microsoft about what I feel they can do better for newbies, like myself, attempting to jump into using their stack for web development.

1. Don't assume anything.  This has to be the biggest area of frustration for me.  There seems to be an underlying assumption that a lot of incoming MVC devs are former web forms devs.  Similarly, there's an assumption that we're comfortable using Visual Studio.  From my personal experience, I do know a little bit of web forms, mostly how horrible the Page object's life cycle is.  I also know what Web.config is used for in an abstract sense, but am certainly not comfortable mucking around in there.  I'm barely competent with VS, having learned the hard way when to build/rebuild a project so it will work right when debugging.  I'm sure others aren't even at that level when they start down this rabbit hole.

2. Ignored or glossed-over info.  This really should be considered 1A.  Again, there's an assumption being made that people are familiar with ASP.NET and are mostly just migrating to MVC and/or EF4.  Look at the model binding validation fiasco I went through earlier.  Even better, look at the route problem I'm currently facing. 

I own what could likely be considered the tome on MVC 2 - Steven Sanderson's Pro ASP.NET MVC 2 Framework.  It is a great book which explains every part of the framework.  In fact, there's an excellent chapter (Chapter 8) which describes, in detail, MVC's routing mechanism.  What it doesn't explain is how to handle malformed routes.  Web.config's customErrors tag is mentioned just once, in passing, on page 612 in Chapter 17, which is dedicated to deploying MVC 2 projects.  That's it.  No description about what customErrors is, nothing about bad routes at all, no hints on making route errors fit into the rest of the routing system, or anything else.  I can't fault the book for not addressing my EF4 issue, as it works with LINQ to SQL instead, but shouldn't malformed routes at least be addressed briefly?

I'm not trying to crap on the book or its author.  I've found, that aside from the bad route issue, it's a great book, and recommend it to anyone looking to join in the MVC 'fun'.  What I'm trying to illustrate is a pattern.  If one of the framework's best books neglects to mention something that is fairly important like handling bad routes, then how are we beginners supposed to know what the hell to do?  It's certainly not addressed (at least, not addressed well) in the demoware, which is where most newbies start.

3. Smaller gripe: where's the at-a-glance info?  I want to know what kind of debugging errors I can step through compared to those I can't.  I want to know what those step-through errors would mean in a live, release environment.  I want to see the differences between Entity Framework 4.0 vs. 4.1, and how the common patterns have changed.  I'm sure this info exists somewhere, but its spread throughout the ether, buried in articles and blog posts.

So, now that I've vented a bit, I have some constructive suggestions on how to make the newbie experience better.

1. Don't assume we come from web forms country.  My background is in PHP.  I've used a grand total of 1 MVC framework in that environment - Kohana 2.something - and it doesn't exhibit any of the Microsoft idiosyncrasies like Web.config.  My IDE of choice back then was Notepad++.  A lot of other wannabe MVC devs comes from similar, or even NO web development backgrounds.  Keep this in mind.  I'm sure a lot of us are willing to skip over the bare-bones basic info we already know if it means you're actually covering all the basics.  I'd rather be inundated with the "No shit, can we move on?" stuff than not.

2. With that said, maybe create a newbie starter pack filled with the info we need to know before diving into MVC as a whole.  Topics could include basic Visual Studio usage (ex: knowing which errors can be stepped through, those that can't, and the differences between them), the basics of ASP.NET (things that are shared between web forms and MVC, like Web.config), and basic C# (ex: LINQ, lambdas, etc.).  If there's a minimum requirement or some prerequisite we need to know before getting into MVC for real, as there seems to be, then why not provide it in a centralized manner?

3. Be thorough.  Books, at least, shouldn't gloss over anything.  I'd rather have the option to dig through the innards of the framework than not.  Again, more information, not less.

In closing, I like the idea behind MVC, and I'm trying to buy, literally, into the platform.  I'd like it if it didn't seem like Microsoft and supporters of the framework made it easier for me to do so.  I'm not looking for anyone to hold my hand or write my code.  I just want the tools in order to do it on my own.

Friday, April 22, 2011

I would write 500 lines, and I would write 500 more

So, I've made a smidgen of progress regarding custom errors.  Some success, mostly failure, but the failure is a different kind of failure, which gives me hope.

The details can be seen at: http://stackoverflow.com/questions/5761573/a-couple-of-errors-when-trying-to-use-custom-errors-in-mvc-2

Paperboy

Routes.  They're one of the key features of MVC, and custom routes are fairly simple to implement.  Just go into Global.asax, and pay attention to how the default route is set up.  The only caveat is that routes must be placed in a particular order - most specific first - in order to work.  Any gamers in the audience who have played either Final Fantasy XII or the Dragon Age games will understand when I say that routes work like Gambits and Tactics, respectively (nerd high five!).

But what if a route fails?  Welcome to my current situation.

From where I sit, route failure happens when one of two things happen:

1. The path is legit, but the parameter(s) is/are wrong, so no data can be retrieved, which results in a view error when the view attempts to display model data that doesn't exist.

2. There's a general flaw with the path, so either the controller or action name is screwed up and the routing system can't find a matching controller-action pair.

In both cases, something is 'not found'.  Sounds like a 404 to me.

Now, maybe it's because I'm still in debug-mode development at this stage, but both kinds of route failure result in a YSOD for me, neither of which mention a 404 not found error.  The first gives me a NullReferenceException, which makes sense as the view is attempting to display properties a a null object.  The second gives me a Ninject exception (I forgot what it was, exactly, and won't be able to get on my development machine until later tonight, so I apologize for the lack of detail), which again makes sense as the controller-action pair is invalid, and Ninject can't find anything which would match it.

What is odd to me is that neither throws a 404.  Again, maybe that's because I'm in debug-mode, and it's showing me errors rather than a useless (for development) 404.  That said, when I apply the [HandleError] attribute to an action, it still doesn't give me the default MVC Error view, which is a bit disconcerting.

So, I'm left wondering what to do.  I've found a variety of answers, ranging from simply turning on custom errors in Web.config to things a bit more... robust, like this: http://stackoverflow.com/questions/619895/how-can-i-properly-handle-404s-in-asp-net-mvc/2577095#2577095  I'm not sure what I should try, or if I'll even see a difference while still in debug-mode.

I'd love to hear how the pros address this, or if it even needs to be addressed at all.

Model binder? I hardly even know her!

The biggest stumbling block I've encountered, so far, was regarding incoming model validation.  Like a good boy, I was (and still am) using Entity Framework 4 for my ORM needs.  Following the examples in the various tutorials I found, my HttpPost method was binding its data straight onto an EF4 entity.  The entity was simple, so simple that I didn't use a view model.  It had a total of four properties, two of which didn't need to be handled by the form (its ID and its LastModified DateTime, which I was originally going to supply in the controller).  I was attempting to test MVC's form validation with Data Annotations when the problem came up - I was getting a ConstraintException from the bowels of EF4.

The exception itself was easy to decipher.  My backing db columns were all set to 'NOT NULL', which was done purposely (I want all articles to have titles, and an article cannot exist without an ID or text.  LastModified is for my own book keeping).  What was odd to me, at the time, was that EF4's entity validation was firing before I even attempted to call SaveChanges().  This validation was triggered right when MVC attempted to bind the incoming form data to an entity.  Since some of the values were purposely empty, they were received as null values, and that, in turn, violated the contract between entity and db.

For a look at the particulars, go here: http://stackoverflow.com/questions/4703085/entity-framework-4-w-mvc-2-fighting-against-ef4s-inability-to-allow-empty-str

This drove me nuts.  Nothing was mentioned about EF4 validation being triggered by MVC model binding.  I scoured over the MVC Music Store demo, and, at the time, there was no mention of it.  I asked Julie Lerman through Twitter, where she was more than gracious with her time and effort, but we couldn't figure out the problem.  I found a workaround on Stack Overflow - there's a Data Annotation attribute which does the trick: [DisplayFormat(ConvertEmptyStringToNull = false].  It worked, but it felt sloppy.  It also didn't address why this was happening.

I eventually found something of an answer here: http://mvcmusicstore.codeplex.com/workitem/6604  The problem for me was that I couldn't step through the error as Jon Galloway claimed.  I'd get the ConstraintException, then a YSOD.  In fact, the YSOD was what alerted me to the error.

I'm still wondering why validation would/should care whether or not an entity in memory has null properties, especially when that entity is not attached to an ObjectContext.  Shouldn't that kind of exception only be raised when one attempts to store the entity back in the db after it's been (re)attached to the ObjectContext?  Seems a bit restrictive to me.

So, the workaround works, but I'm going to change over to custom edit models for incoming data, then transfer that data to an entity.  It will allow me to apply Data Annotations for simple UI layer validation without forcing me to add it to my domain layer entities.  I also don't like relying on the [DisplayFormat] attribute in general.  It has a bad code smell to me.

The beginning of the end is the middle... or something

The first post is always the hardest, so forgive me if this is a bit rambling.

In short, I'm an amateur web developer trying to become a professional.  I'm self-taught (aren't we all?), and certainly not a natural at it.  I'm the guy who has to read, then re-read, then re-re-read code, then try it myself, inevitably cursing the person/people who wrote the example code before seeing that, no it really was my mistake after all.  And even after all that, I'm still barely confident in what I know.  Yeah, I'm that guy.

I'm also, technically, a company.  That's right, I have my LLC, even though it's really just me.  Saying I'm the CEO of a company is a hell of a lot more impressive than the reality of the situation.  It's also easier to put on business cards.

I'm sort of caught between a rock and a hard place at the moment.  I can't really work an 8 hr/day, 40/hr (or more) a week job due to my physical disability.  There's a whole bunch of logistical stuff that comes along with it (like, say, eating and going to the bathroom), and there are also issues with pressure sores.  So, my best bet is with freelancing.  And therein lies the rub.

Freelancing is all about reputation.  I have none.  Most of the work I have done is small, and most of it lies behind the scenes.  PHP stuff here, JavaScript stuff there, but nothing to hang my hat on, and certainly nothing to brag about.  So, I've come up with a foolproof plan.  I think.

I'm going to make two ASP.NET MVC sites.  I'm already halfway or so done with the first (hence my oh-so-clever title), which is written in MVC 2, and its sister site will immediately follow and be written in MVC 3.  These sites will be content-driven, with the content coming from myself and one other person who wishes to be anonymous (yes, she exists.  no, she's not one of the voices in my head.  or a sock puppet).

With this plan, I'm hedging my bets.  I'm creating tangible projects to showcase in my portfolio, which will greatly enhance my ability to get some real work my way.  I'm also hoping I can make some money, even if it's just towards hosting costs, from them.  Finally, I'm forcing myself to learn things I should know.

So, where does this blog fit into the whole thing?  I've found that writing my first MVC 2 site hasn't been nearly as easy as the various resources I've found on the subject led me to believe.  A lot of things are either ignored or glossed over, even in the books I've read/own.  I hope that charting my own successes and failures will help others who have stumbled into the same gaps.  At the very least, this blog may provide some anthropological interest.