views:

77

answers:

2

hopefully there's an easy solution to this one.

I have my MVC2 project which allows uploads of files on certain forms. I'm trying to keep my controllers lean, and handle the processing within the business layer of this sort of thing.

That said, HttpFileCollectionBase is obviously in the System.Web assembly.

Ideally I want to call to something like:

UserService.SaveEvidenceFiles(MyUser user, HttpFileCollectionBase files);

or something similar and have my business layer handle the logic of how and where these things are saved.

But, it feels a little icky to have my models layer with a reference to System.Web in terms of separation of concerns etc.

So, we have (that I'm aware of) a few options:

  1. the web project handling this, and my controllers getting fatter
  2. mapping the HttpFileCollectionBase to something my business layer likes
  3. passing the collection through, and accepting that I reference System.Web from my business project

Would love some feedback here on best practice approaches to this sort of thing - even if not specifically within the context of the above.

+2  A: 

I'd just use a custom model binder if you want to keep the logic out of your controllers - then you can stick the extracted data into the model which you can do what you want with.

http://www.heartysoft.com/post/2010/05/06/ASPNET-MVC-ModelBinding-Multiple-File-Uploads-to-an-Array.aspx

Clarification - I consider model binders and other interception techniques to be a convenient way of splitting logic out of controllers and into separately maintainable containers - this is infrastructure code/web logic and thus does not belong in the business logic and thus can reference System.Web etc happily.

Clarification - Effectively this is your Option 2 in disguise, you use model binders to map the unfriendly data into something the rest of your code can recognise, but you do it in a way that doesn't compromise your clean controllers.

Rob Ashton
hey Rob :) maybe not been clear - the binding of it all is fine, it's what I do when I need to get that collection down to a separate business layer project. The example there still uses HttpPostedFileBase (System.Web) so my business layer still would need a ref if I chose to handle that down in the business layer project?
Terry_Brown
If you use a custom model binder, your controller never gets a HttpPostedFileBase, which means you never pass anything from System.Web into your business logic, which means you don't need to worry about references.Modelbinders = Web logic, not business logic
Rob Ashton
Essentially this means you keep your controller lean, which facilitates testing and maintainability, and you delegate some horrible mapping logic into a model binder, and the rest of your code happens as if the model binder doesn't exist at all.
Rob Ashton
ahhh, fantastic Rob - yup, that helps a lot - cheers man. Now to read up some more on modelbinders! lol
Terry_Brown
A: 

assuming you can't easily mock up HttpFileCollectionBase you could pass in something like Dictionary<String, MyFile> where MyFile wraps HttpPostedFile. if HttpFileCollectionBase can easily be mockable for unit tests i see no point.

drscroogemcduck
using `HttpPostedFile` still means the business layer depends on `System.Web` doesn't it?
oedo
did you mean MyFile 'wraps' HttpPostedFile or 'maps'? I can see how my web layer would 'map' comfortably to 'a.n.other' format and then it wouldn't matter if my front end was web/desktop/something else, so long as they knew how to map to that underlying format. If it's wrapping, then oedo is right, you'd still need System.Web in the business layer project - I guess my question is 'is that bad?' - from a pure modelling aspect, it feels it, but....?
Terry_Brown