Search code examples
asp.net-mvchelpersyndication-feed

Where do you put methods for common web uri paths


We have a pretty common architecture:

Database

Repository Layer

Business Objects

Services Layer - serves DTOs to the client

Web Layer (MVC)

We've got a number of common paths to resources, in particular images and podcasts (Ex. http://media.mysite.com/podcasts/). I want to create a static utility class with properties:

MySite.Utils.ImagePathUri

MySite.Utils.PodcastsPathUri

etc

My question is: Where do you put uri paths? Into which project does this utility class go?

Initially, it seemed a no-brainer: the web layer. It's a web site. I should be able to change the urls of a site without the other layers knowing about it.

Everything was fine, but, . . . then one day one of my services needed to provide a SyndicationFeed type. The SyndicationFeed needs a full URI, not just a partial file name. But the services shouldn't have access to full paths. Or should they?

I've debated with myself several things, but can't come up with a firm position:

  1. Move the paths to the services layer. That tightly couples the web layer to the services layer, but maybe that's ok, since they're pretty tightly coupled to begin with.
  2. Move the paths to the business objects or repos. I don't like this, but if I'm open to putting it into the services layer, I have to at least consider it.
  3. Don't use SyndicationFeed inside of services layer, but use it only in the web layer. Solves the issue, but it seems like SyndicationFeed should belong in a services layer.
  4. Discard SyndicationFeed. Any SyndicationFeed can more easily be created in MVC with a PartialView that generates the appropriate XML without having to mess with the bloated abstractions like ElementExtensions. I like this one, but we're using SyndicationFeed in a number of places, so that one will take the most explaining to do.
  5. Provide a fake uri to the syndication feed in the services layer and then change it in the web layer. Can you say hack?
  6. Put the full path in the database. That sounds ok at first, but then I realize that it breaks as soon as you have a dynamically generated image.
  7. Some other solution that doesn't occur to me.

What are your thoughts? Where do you put utility classes for web resources (images, podcasts, etc)? And if you say "web layer", what's your take on the SyndicationFeed issue?

UPDATE

At the end of the day, I decided to scrap the SyndicationFeed class, which negated the need for including the path to the file in the service and repository layers. However, the problem still comes up elsewhere and using DI and, in particular, an IoC like Ninject makes perfect sense. So does wrapping together these into a common interface.

SyndicationFeed, View engines and why Declarative does Declarative better

I ditched the SyndicationFeed and instead created the XML that I needed using Razor. Not only is it much easier to create, but it's 1000% more readable. I've come around to the opinion that using imperative code (C#, VB, etc.) to create XML is just harder than it ought to be. XML is declarative, not imperative.

Instead, I've now decided that declarative syntax of View Engines (e.g. Razor) is much easier to work with than imperative languages.


Solution

  • I feel your pain. I too had a similar situation that I resolved by passing the uri to my repository layer, from my web layer.

    My project uses Ninject for binding, and since I was already passing the connection string to the repository with Ninject, it was a simple matter to pass my path string as well.

    My repository then massages the path string and populates the necessary properties in my business object.

    Is this proper? I do not know, but it works for now. I am not completely happy with the solution, but I have not yet had a chance attempt an improvemnt.

    Would love to hear how others have dealt with this.