Best asp.net-mvc questions in June 2011

One big repository vs. many little ones?

13 votes

I have several product tables in my database:

  • ProductTypes
  • ProductCategories
  • ProductCategoryItems
  • ProductInventory

The way I see it now, I can make IProduct which would have methods such as:

  • FindAllTypes()
  • FindAllCategories(int typeId)
  • FindAllItems(int categoryId)

Or, I can separate each to mimic the table structure: IProductType, IProductCategory, etc.

Is there a reason to go with one over another?

The idea of repositories is to delegate each one with responsibility for a single entity. In this case making a repository for each entity is recommended. You can go for the big repository one as well, but is not the best solution. In the end you'll get a HUGE class with lots of methods and really tight coupled. Also difficult to give maintenance to.

Real examples of ASP.NET MVC code refactored for Dependency Injection using Ninject

9 votes

Good morning!

Yesterday I watched Tekpub's amazing video "Dependency Injection and Inversion of Control" and it blew my mind. I feel like this is how I should be writing code. I have watched it before and even experimented with Ninject a little bit, but feel like I need some more examples of code being refactored into this paradigm.

The brief MUD example he goes into is great, but does anyone know of a site or project where they start with some ugly, but working, code and then refactor it into clean Dependency Injected code?

While I can find examples of code that use Dependency Injection pretty easily, I am having a hard time finding before/after code and I feel like this would greatly help me start programming "at the next level". I need a few more examples to really wrap my head around it.

Suppose you wanted to implement a spelling correction service. Input a word/phrase and out pops a corrected version of the word/phrase. What if you were depending on a large, online provider that went down for a day. Ideally, you would implement a backup in case the request to said provider failed. In that backup, you might call your secondary service and hope they're online. Maybe in a last ditch effort in the event they're both down, you implement an offline provider to correct spelling based on a local dictionary that exists on the file system.

How do you manage multiple providers like this?

Before

public class SpellCheck
{
    public string FixText(string text)
    {
        string CorrectedText = string.Empty;
        // create HTTP request to Online Provider #1
        // return CorrectedText;
    }
}

After

public class SpellCheck
{
    private readonly IOnlineSpellService _onlineSpell;
    private readonly IOfflineSpellService _offlineSpell;

    public SpellCheck(IOnlineSpellService onlineSpell, 
        IOfflineSpellService offlineSpell)
    {
        this._onlineSpell = onlineSpell;
        this._offlineSpell = offlineSpell;
    }

    // same method as before, just a slightly different implementation
    public string FixText(string text)
    {
        string fixedText = _onlineSpell.FixText(text);
        if(_onlineSpell.Failed)
            fixedText = _offlineSpell.FixText(text);

        return fixedText;
    }
}

Of course, you'd need to implement the interface ISpellOnlineService (and similar interface for ISpellOfflineService

public interface ISpellOnlineService
{
    public bool Failed { get; set; }
    public string FixText(string text);
}

Next, implement your spelling providers (both online and offline, or even multiple instances of both to gain more flexibility)

public class OnlineProviderNo1 : IOnlineSpellService
{
    public string FixText(string text)
    {
        // implement online logic
        this.Failed = false;
    }
}

Finally, register your services by overriding the CreateKernel method and subclassing your MvcApplication from NinjectHttpApplication. And apparently with Ninject you replace Application_Start with an override called OnApplicationStarted like so:

**This done in global.asax

public class MvcApplication : NinjectHttpApplication
{
    // ...

    protected override void OnApplicationStarted()
    {
        base.OnApplicationStarted();

        AreaRegistration.RegisterAllAreas();
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

    protected override IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<IOnlineSpellService>().To<OnlineProviderNo1>();
        kernel.Bind<IOfflineSpellService>().To<OfflineProviderNoX>();

        return kernel;
    }
}

Yes, this is a real world example, as I've implemented it (I actually used Castle Windsor, but it's the identical concept with Ninject--just adapted above) with 3 online providers and 2 offline providers. In CreateKernel you may choose to include logic to examine a database, config file, etc to determine which provider to register. For example, maybe one service has announced 24 hours of downtime (hopefully, you're lucky enough to have that announced!) so during that time you want to switch to another online provider for which you've implemented an instance of IOnlineSpellService

How to modify ASP.NET MVC static file root

8 votes

I want to be able to reorganize my ASP.NET MVC site structure to more closely match the way Rails does it (We do both rails and ASP.net at my company).

In Rails, there is a "public" folder that behaves as the root of the site. For example, I could drop in a "test.html" and access the file with the url http://domain.com/test.html which would serve up the static html file.

In asp.net MVC there is a "Content" folder that I want to behave as the root. So instead of accessing http://domain.com/content/myfile.html, i want to be able to do http://domain.com/myfile.html.

I know I can just drop the file in the root of the project, but i need to do this with many files including css, js, html, images, etc and want to share some standardized assets across rails and aspnetmvc.

Is there a way to do this?

There is another possible solution. Instead of using code, you can use a rewrite rule to handle this for you. If you are using IIS 7 or above, you can use Microsoft's URL Rewrite Module.

A rule like the following would probably do it:

<rule name="Rewrite static files to content" stopProcessing="true">
  <match url="^([^/]+(?:\.css|\.js))$" />
  <conditions>
      <add input="{APPL_PHYSICAL_PATH}content{SCRIPT_NAME}" matchType="IsFile" />
  </conditions>
  <action type="Rewrite" url="/content/{R:1}" />
</rule>

The rule checks for a request to a css or js file off the root of the site. Then it checks to see if the file exists in the content folder. If it exists, then the rewrite will return the file in the content folder. I've only tested this a little bit, but it seems to work. It certainly needs more testing, and possible refinement.

How to ignore current route values when generating links?

7 votes

The question is similar to asp.net mvc Html.ActionLink() keeping route value I don't want, but with a twist that makes it more complex.

Starting from a default new MVC3 app, I change the routes to:

routes.MapRoute(
    "r1", // Route name
    "{controller}/{id}/{action}"
);

routes.MapRoute(
    "r2", // Route name
    "{controller}/{action}"
);

Notice that the id comes before the action in the first.

Then in Home\Index.cshtml, I add:

@Url.Action("Index")
@Url.Action("Index", new { id = "blah" })
@Url.Action("Index", new { id = "" })

Now I navigate to /Home/Foo/Index and look at the 3 generated links. I get

  1. "/Home/Foo/Index"
  2. "/Home/blah/Index"
  3. "/Home/Index?id=Foo"

The first two make sense, and are using the first route.

But in the third link, which hits the second route, I don't understand why id=Foo is passed on the query string, given that I explicitly passed an empty id. I would expect it to just generate "/Home/Index".

Can anyone explain that, and suggest how I can get it not to show up?

I just tested this and it seems to work ok.

Url.Action("Index", new { id = UrlParameter.Optional })

generates

/Home/Index

MVC: I need to understand the Model

6 votes

I've been working with the MVC pattern for a while now, but I honestly don't feel like I truly understand how to work with and apply the "Model" ... I mean, one could easily get away with using only the Controller and View and be just fine.

I understand the concept of the Model, but I just don't feel comfortable applying it within the pattern... I use the MVC pattern within .NET and also Wheels for ColdFusion.

"the Model represents the information (the data) of the application and the business rules used to manipulate the data" - yes, I get that... but I just don't really understand how to apply that. It's easier to route calls to the Controller and have the Controller call the database, organize the data and then make it available to the View. I hope someone understands where my confusion resides...

I appreciate your help in advance!

Look at it like this. When your client requests a page this is what happens (massively trimmed):

  • He ends up at your controller

  • The controller gets the necessary data from your model

  • The controller then passes the data to the view which will create your HTML

  • The controller sends the HTML back to the client

So client -> controller -> model -> controller -> view -> controller -> client

So what is the model? It is everything that is required to get the data required for you view!

  • It is services

  • It is data access

  • It is queries

  • It is object mapping

  • It is critical 'throw exception' style validation

Your controller should not be writing your queries if you are sticking to the pattern. Your controller should be getting the correct data required to render the correct view.

It is acceptable for your controller to do a few other things such as validating posted data or some if/else logic but not querying data - merely calling services (in your model area) to get the data required for your view.

I'm trying to use the mvc-mini-profiler with EFCodeFirst I'm creating a DbProfiledConnection and passing it to the DbContext on construction as below. The application continues to work as expected by the sql is not exposed to the Profiler.

public class WebContext : DbContext
{
    static DbConnection _connection = new SqlConnection(ConfigurationManager.ConnectionStrings["WebContext"].ConnectionString);
    static DbConnection _profiledConnection = MvcMiniProfiler.Data.ProfiledDbConnection.Get(_connection);        

    public WebContext()
            : base(_profiledConnection, true)
    {   

    }

oops my bad.

I've modified it so that when my WebContext is constructed in my UnitOfWork i pass in a ProfiledDbConnection

public UnitOfWork()
{             
    var profiledConnection = MvcMiniProfiler.Data.ProfiledDbConnection.Get(connection);
    this.context = new MyContext(profiledConnection);
}

I've checked and MiniProfier Current has been set in Application_BeginRequest and it returns a ProfiledDbConnection when I then try and query the database an error is thrown in the ProfiledDbProviderServices class.

 protected override string GetDbProviderManifestToken(DbConnection connection)
 {
     return tail.GetProviderManifestToken(connection);
 }

this method returns a "The provider did not return a ProviderManifestToken string." error

I suspect this relates to the static field initializer. Connections on web apps should never be static anyway (but request-specific at most).

The key is: what does ProfiledDbConnection actually come out as? The Get method returns a ProfiledDbConnection only if you are currently profiling (on the current request), and the connection is profiled against the MiniProfiler instance on that request.

If you use a static field, then there are two scenarios:

  • the static field is initialized without a request context (or a non-developer request context): no profiling will occur as MiniProfiler.Current is null
  • the static field is initialized, but everything is logged against the very first request, which is quickly dead

How to parse and execute a command-line style string?

5 votes

Okay, this question is going to be a bit long-winded but hopefully it will be an interesting one to you. I do have a specific question at the end but I want to provide plenty of background and context so that you are on the same page as much as possible and can understand my objective. If lengthy questions aren't your style that's totally fine. However, if you would like to contribute all I ask is that you try your best to understand the vision and be on the same page as much as possible.

Bounty Notice

If you just want to get to the bounty details section, please scroll toward the bottom and find the header "Bounty Update".

Background

I am building a console-style application with ASP.NET MVC 3. It is located at http://www.u413.com if you need to go there and get an idea of how it operates. The concept itself is simple: receive command strings from the client, check if the command supplied exists and if the arguments provided with the command are valid, execute the command, return a set of results.

Inner-workings

With this application I decided to get a little creative. The most obvious solution to a terminal-style application is to build the world's largest IF statement. Run every command through the IF statement and call the appropriate functions from within. I did not like this idea. In an older version of the application this was how it operated and it was a huge mess. Adding functionality to the application was ridiculously difficult.

After much thought I decided to build a custom object called a command module. The idea is to build this command module with each request. The module object would contain all available commands as methods and the site would then use reflection to check if a command supplied by the user matches a method name. The command module object sits behind an interface called ICommandModule shown below.

namespace U413.Business.Interfaces
{
    /// <summary>
    /// All command modules must ultimately inherit from ICommandModule.
    /// </summary>
    public interface ICommandModule
    {
        /// <summary>
        /// The method that will locate and execute a given command and pass in all relevant arguments.
        /// </summary>
        /// <param name="command">The command to locate and execute.</param>
        /// <param name="args">A list of relevant arguments.</param>
        /// <param name="commandContext">The current command context.</param>
        /// <param name="controller">The current controller.</param>
        /// <returns>A result object to be passed back tot he client.</returns>
        object InvokeCommand(string command, List<string> args, CommandContext commandContext, Controller controller);
    }
}

The InvokeCommand() method is the only method on the command module that my MVC controller is immediately aware of. It is then this method's responsibility to use reflection and look at the instance of itself and locate all available command methods.

I use Ninject for dependency injection. My MVC controller has a constructor dependency on ICommandModule. I built a custom Ninject provder that builds this command module when resolving the ICommandModule dependency. There are 4 types of command modules Ninject can build:

  1. VisitorCommandModule
  2. UserCommandModule
  3. ModeratorCommandModule
  4. AdministratorCommandModule

There is one more class BaseCommandModule which all other module classes inherit from. Real quickly, here are the inheritance relationships:

  • BaseCommandModule : ICommandModule
  • VisitorCommandModule : BaseCommandModule
  • UserCommandModule : BaseCommandModule
  • ModeratorCommandModule : UserCommandModule
  • AdministratorCommandModule : ModeratorCommandModule

Hopefully you can see how this is constructed by now. Based on the user's membership status (not logged in, regular user, moderator, etc) Ninject will provide the proper command module with only the command methods the user should have access to.

All of this works great. My dilemma comes in when I am parsing the command string and figuring out how to structure the command methods on the command module object.

The Question

How should the command string be parsed and executed?

Current Solution

Currently I break up the command string (the string passed in by the user containing the command and all arguments) in the MVC controller. I then call the InvokeCommand() method on my injected ICommandModule and I pass in a string command and a List<string> args.

Let's say I have the following command:

TOPIC <id> [page #] [reply “reply”]

This line defines the TOPIC command accepting a required ID number, an optional page number, and an optional reply command with a reply value.

I currently implement the command method like this (The attributes above the method are for help menu information. The HELP command uses reflection to read all these and display an organized help menu):

    /// <summary>
    /// Shows a topic and all replies to that topic.
    /// </summary>
    /// <param name="args">A string list of user-supplied arguments.</param>
    [CommandInfo("Displays a topic and its replies.")]
    [CommandArgInfo(Name="ID", Description="Specify topic ID to display the topic and all associated replies.", RequiredArgument=true)]
    [CommandArgInfo(Name="REPLY \"reply\"", Description="Subcommands can be used to navigate pages, reply to the topic, edit topic or a reply, or delete topic or a reply.", RequiredArgument=false)]
    public void TOPIC(List<string> args)
    {
        if ((args.Count == 1) && (args[0].IsInt64()))
            TOPIC_Execute(args); // View the topic.
        else if ((args.Count == 2) && (args[0].IsInt64()))
            if (args[1].ToLower() == "reply")
                TOPIC_ReplyPrompt(args); // Prompt user to input reply content.
            else
                _result.DisplayArray.Add("Subcommand Not Found");
        else if ((args.Count >= 3) && (args[0].IsInt64()))
            if (args[1].ToLower() == "reply")
                TOPIC_ReplyExecute(args); // Post user's reply to the topic.
            else
                _result.DisplayArray.Add("Subcommand Not Found");
        else
            _result.DisplayArray.Add("Subcommand Not Found");
    }

My current implementation is a huge mess. I wanted to avoid giant IF statements, but all I did was trade one giant IF statement for all the commands, for a ton of slightly less giant IF statements for every command and its arguments. This isn't even the half of it; I simplified this command for this question. In actual implementation there are quite a few more arguments that can be provided with this command and that IF statement is the ugliest thing I have ever seen. It's very redundant and not at all DRY (don't repeat yourself) as I have to display "Subcommand Not Found" in three different places.

Suffice it to say, I need a better solution than this.

The Ideal Implementation

Ideally I would love to structure my command methods something like his:

public void TOPIC(int Id, int? page)
{
    // Display topic to user, at specific page number if supplied.
}

public void TOPIC(int Id, string reply)
{
    if (reply == null)
    {
        // prompt user for reply text.
    }
    else
    {
        // Add reply to topic.
    }
}

Then I'd love to do this:

  1. Receive command string from client.
  2. Pass command string directly into InvokeCommand() on ICommandModule.
  3. InvokeCommand() performs some magic parsing and reflection to choose the right command method with the right arguments and invokes that method, passing in only the necessary arguments.

The Dilemma with the Ideal Implementation

I'm not sure how to structure this logic. I've been scratching my head for days. I wish I had a second pair of eyes to help me out on this (hence finally resorting to a novel of an SO question). In what order should things happen?

Should I pull out the command, find all methods with that command name, then loop through all the possible arguments, then loop through my command string's arguments? How do I determine what goes where and what arguments go in pairs. For instance, if I loop through my command string and find Reply "reply" how do I pair the reply content with the reply variable, while encountering <ID> number and supplying it for the Id argument?

I'm sure I'm confusing the hell out of you now. I'm confusing the hell out of me. Let me illustrate with some examples of command strings the user might pass in:

TOPIC 36 reply // Should prompt the user to enter reply text.
TOPIC 36 reply "Hey guys what's up?" // Should post a reply to the topic.
TOPIC 36 // Should display page 1 of the topic.
TOPIC 36 page 4 // Should display page 4 of the topic.

How do I know to send 36 to the Id parameter? How do I know to pair reply with "Hey guys what's up?" and pass "Hey guys what's up?" as the value for the reply argument on the method?

In order to know which method overload to call I need to know how many arguments where supplied so that I can match that number to the overload of the command method that takes that same number of arguments. The problem is, `TOPIC 36 reply "Hey guys what's up?" is actually two arguments, not three as reply and "Hey guys..." go together as one argument.

I don't mind bloating the InvokeCommand() method a little (or a lot) as long as it means that all the complex parsing and reflection nonsense is handled there and my command methods can remain nice and clean and easy to write.

I guess I'm really just looking for some insight here. Does anyone have any creative ideas to solve this problem? It really is a big issue because the argument IF statements are currently making it very complicated to write new commands for the application. The commands are the one part of the application that I want to be super simple so that they can be easily extended and updated. Here is what the actual TOPIC command method looks like in my app:

    /// <summary>
    /// Shows a topic and all replies to that topic.
    /// </summary>
    /// <param name="args">A string list of user-supplied arguments.</param>
    [CommandInfo("Displays a topic and its replies.")]
    [CommandArgInfo("ID", "Specify topic ID to display the topic and all associated replies.", true, 0)]
    [CommandArgInfo("Page#/REPLY/EDIT/DELETE [Reply ID]", "Subcommands can be used to navigate pages, reply to the topic, edit topic or a reply, or delete topic or a reply.", false, 1)]
    public void TOPIC(List<string> args)
    {
        if ((args.Count == 1) && (args[0].IsLong()))
            TOPIC_Execute(args);
        else if ((args.Count == 2) && (args[0].IsLong()))
            if (args[1].ToLower() == "reply" || args[1].ToLower() == "modreply")
                TOPIC_ReplyPrompt(args);
            else if (args[1].ToLower() == "edit")
                TOPIC_EditPrompt(args);
            else if (args[1].ToLower() == "delete")
                TOPIC_DeletePrompt(args);
            else
                TOPIC_Execute(args);
        else if ((args.Count == 3) && (args[0].IsLong()))
            if ((args[1].ToLower() == "edit") && (args[2].IsLong()))
                TOPIC_EditReplyPrompt(args);
            else if ((args[1].ToLower() == "delete") && (args[2].IsLong()))
                TOPIC_DeleteReply(args);
            else if (args[1].ToLower() == "edit")
                TOPIC_EditExecute(args);
            else if (args[1].ToLower() == "reply" || args[1].ToLower() == "modreply")
                TOPIC_ReplyExecute(args);
            else if (args[1].ToLower() == "delete")
                TOPIC_DeleteExecute(args);
            else
                _result.DisplayArray.Add(DisplayObject.InvalidArguments);
        else if ((args.Count >= 3) && (args[0].IsLong()))
            if (args[1].ToLower() == "reply" || args[1].ToLower() == "modreply")
                TOPIC_ReplyExecute(args);
            else if ((args[1].ToLower() == "edit") && (args[2].IsLong()))
                TOPIC_EditReplyExecute(args);
            else if (args[1].ToLower() == "edit")
                TOPIC_EditExecute(args);
            else
                _result.DisplayArray.Add(DisplayObject.InvalidArguments);
        else
            _result.DisplayArray.Add(DisplayObject.InvalidArguments);
    }

Isn't that ridiculous? Every command has a monster like this and it's unacceptable, but I'm at the end of my rope. I am hurting my brain sitting here staring for hours on end just going over scenarios in my head and how code might handle it. I was pretty proud of my command module setup, now if I could just be proud of the command method implementation...

Unless I get some really brilliant suggestions right off the bat then I plan to keep this question unanswered for a while so that I can get a fair amount of ideas.

While I'm not looking to jump ship with my entire model (command modules) for the application, I am definitely open to suggestions. I'm mostly interested in suggestions related to parsing the command line string and mapping its arguments to the right method overloads. I'm sure whatever solution I go with will require a fair amount of redesign so don't be afraid to suggest anything you think is valuable, even if I don't necessarily use your suggestion it may put me on the right track.

Edit: Making a long question longer

I just wanted to clarify real quick that the mapping of commands to command methods is not really something I'm worried about. I'm mostly concerned about how to parse and organize the command line string. Currently the InvokeCommand() method employs some very simple C# reflection to find the appropriate methods:

    /// <summary>
    /// Invokes the specified command method and passes it a list of user-supplied arguments.
    /// </summary>
    /// <param name="command">The name of the command to be executed.</param>
    /// <param name="args">A string list of user-supplied arguments.</param>
    /// <param name="commandContext">The current command context.</param>
    /// <param name="controller">The current controller.</param>
    /// <returns>The modified result object to be sent to the client.</returns>
    public object InvokeCommand(string command, List<string> args, CommandContext commandContext, Controller controller)
    {
        _result.CurrentContext = commandContext;
        _controller = controller;

        MethodInfo commandModuleMethods = this.GetType().GetMethod(command.ToUpper());
        if (commandModuleMethods != null)
        {
            commandModuleMethods.Invoke(this, new object[] { args });
            return _result;
        }
        else
            return null;
    }

So as you can see, I'm not worried about how to find the command methods as that is already working. I'm just pondering a good way to parse the command string, organize arguments, and then using that information to pick the right command method/overload using reflection.

BOUNTY UPDATE

I have started a bounty on this question. I am looking for a really good way to parse the command string I'm passing in. I want the parser to identify several things:

  • Options. Identify options in the command string.
  • Name/Value Pairs. Identify name/value pairs (e.g. [page #] <- includes keyword "page" and value "#")
  • Value Only. Identify value only.

I want these to be identified via metadata on the first command method overload. Here is a list of sample methods I want to write, decorated with some metadata to be used by the parser when it is doing reflection. I will give you these method samples and some sample command strings that should map to that method. Then I will leave it up to you fine SO folk to come up with a good parser solution.

// Metadata to be used by the HELP command when displaying HELP menu, and by the
// command string parser when deciding what types of arguments to look for in the
// string. I want to place these above the first overload of a command method.
// I don't want to do an attribute on each argument as some arguments get passed
// into multiple overloads, so instead the attribute just has a name property
// that is set to the name of the argument. Same name the user should type as well
// when supplying a name/value pair argument (e.g. Page 3).

[CommandInfo("Test command tests things.")]
[ArgInfo(
    Name="ID",
    Description="The ID of the topic.",
    ArgType=ArgType.ValueOnly,
    Optional=false
    )]
[ArgInfo(
    Name="PAGE",
    Description="The page number of the topic.",
    ArgType=ArgType.NameValuePair,
    Optional=true
    )]
[ArgInfo(
    Name="REPLY",
    Description="Context shortcut to execute a reply.",
    ArgType=ArgType.NameValuePair,
    Optional=true
    )]
[ArgInfo(
    Name="OPTIONS",
    Description="One or more options.",
    ArgType=ArgType.MultiOption,
    Optional=true
    PossibleValues=
    {
        { "-S", "Sort by page" },
        { "-R", "Refresh page" },
        { "-F", "Follow topic." }
    }
    )]
[ArgInfo(
    Name="SUBCOMMAND",
    Description="One of several possible subcommands.",
    ArgType=ArgType.SingleOption,
    Optional=true
    PossibleValues=
    {
        { "NEXT", "Advance current page by one." },
        { "PREV", "Go back a page." },
        { "FIRST", "Go to first page." },
            { "LAST", "Go to last page." }
    }
    )]
public void TOPIC(int id)
{
    // Example Command String: "TOPIC 13"
}

public void TOPIC(int id, int page)
{
    // Example Command String: "TOPIC 13 page 2"
}

public void TOPIC(int id, string reply)
{
    // Example Command String: TOPIC 13 reply "reply"

    // Just a shortcut argument to another command.
    // Executes actual reply command.
    REPLY(id, reply, { "-T" });
}

public void TOPIC(int id, List<string> options)
{
    // options collection should contain a list of supplied options

    Example Command String: "TOPIC 13 -S",
                            "TOPIC 13 -S -R",
                            "TOPIC 13 -R -S -F",
                            etc...
}

The parser must take in a command string, use reflection to find all possible command method overloads, use reflection to read the argument attributes to help determine how to divide up the string into a proper list of arguments, then invoke the proper command method overload, passing in the proper arguments.

Let me know if you need any clarification.

Any help is appreciated. Thanks everyone!

PS - If you're interested at all in taking a peek at the source code for the application, it is open source and located at http://u413.googlecode.com. Currently I am the only developer but if you find yourself interested in the project then drop me a line as per the instructions on the project page.

Be aware that you can put attributes on parameters which might make things more readable, e.g.

public void TOPIC (
    [ArgInfo("Specify topic ID...")] int Id, 
    [ArgInfo("Specify topic page...")] int? page) 
{
    ...
}

What's a clean/DRY way to show available operations on user content?

5 votes

Working on an ASP.NET MVC 3 (Razor) application, that's mainly concerned with UGC (user generated content).

I'm working on a "Q&A" area - where users can ask questions, others can answer, vote, etc.

As such, i'm trying to figure out a clean way to handle the available operations a user can do on any given page, based on their role and other factors.

Take the scenario of the "Question Detail Page" (like this page on Stack Overflow).

Any (authenticated) user can:

  • Vote for question/answer
  • Answer

Question owner can:

  • Edit
  • Delete
  • Mark answer

And so forth.

Now, i have a QuestionViewModel, that is used to display the question and relevant answers for this particular View.

I create it using AutoMapper.

How can i display "stickies" (e.g hyperlinks) on the page, based on the available operations?

My current thinking is:

  • I create an enum: QuestionOperation (Answer, Edit, Disable, Vote, Answer, etc)
  • I add a property of type IEnumerable<QuestionOperation> to my ViewModel
  • I set this property in my action method (HTTP GET), checking if the user is authenticated and the roles they are a part of.
  • I then use an editor template to render out each operation as a hyperlink, using Html.ActionLink

Is that considered a clean approach - or can anyone suggest a better one?

Keeping in mind i am re-using this QuestionViewModel on three pages:

  1. The question detail page
  2. The "Ask a question" page
  3. The "Edit a question" page

So because these operations are page/user dependant, it can't really be done with AutoMapper.

I would setup a separate controller and action which will be returning a partial view containing the necessary links. Then I would use the Html.Action helper to include it from the main view.

Something among the lines:

public class UserLinksController: Controller
{
    // TODO: ctor DI of a repository, etc...

    public ActionResult Index(string questionId)
    {
        string username = User.Identity.IsAuthenticated 
            ? User.Identity.Name : string.Empty;
        var roles = _repository.GetRolesForQuestion(username, questionId);
        var model = Mapper.Map<UserRoles, RolesViewModel>(roles);
        return PartialView(model);
    }
}

and in the corresponding partial you would check the view model and render the necessary links:

@model RolesViewModel
@if(Model.CanEdit)
{
    @Html.ActionLink("Edit", "Edit", "Questions")    
}
@if(Model.CanDelete)
{
    @Html.ActionLink("Delete", "Delete", "Questions")    
}
...

Now somewhere in your main view simply include this action using the Html.Action method:

@Html.Action("Index", "UserLinks", new { questionId = Model.QuestionId })

Best way to structure the code for an ASP.NET MVC REST API that is decoupled from the data formats?

5 votes

I am creating a REST API in ASP.NET MVC. I want the format of the request and response to be JSON or XML, however I also want to make it easy to add another data format and easy to create just XML first and add JSON later.

Basically I want to specify all of the inner workings of my API GET/POST/PUT/DELETE requests without having to think about what format the data came in as or what it will leave as and I could easily specify the format later or change it per client. So one guy could use JSON, one guy could use XML, one guy could use XHTML. Then later I could add another format too without having to rewrite a ton of code.

I do NOT want to have to add a bunch of if/then statements to the end of all my Actions and have that determine the data format, I'm guessing there is some way I can do this using interfaces or inheritance or the like, just not sure the best approach.

Serialization

The ASP.NET pipeline is designed for this. Your controller actions don't return the result to the client, but rather a result object (ActionResult) which is then processed in further steps in the ASP.NET pipeline. You can override the ActionResult class. Note that FileResult, JsonResult, ContentResult and FileContentResult are built-in as of MVC3.

In your case, it's probably best to return something like a RestResult object. That object is now responsible to format the data according to the user request (or whatever additional rules you may have):

public class RestResult<T> : ActionResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        string resultString = string.Empty;
        string resultContentType = string.Empty;

        var acceptTypes = context.RequestContext.HttpContext.Request.AcceptTypes;

        if (acceptTypes == null)
        {
            resultString = SerializeToJsonFormatted();
            resultContentType = "application/json";
        }
        else if (acceptTypes.Contains("application/xml") || acceptTypes.Contains("text/xml"))
        {
            resultString = SerializeToXml();
            resultContentType = "text/xml";
        }

       context.RequestContext.HttpContext.Response.Write(resultString);
        context.RequestContext.HttpContext.Response.ContentType = resultContentType;
   }
}

Deserialization

This is a bit more tricky. We're using a Deserialize<T> method on the base controller class. Please note that this code is not production ready, because reading the entire response can overflow your server:

protected T Deserialize<T>()
{
    Request.InputStream.Seek(0, SeekOrigin.Begin);
    StreamReader sr = new StreamReader(Request.InputStream);
    var rawData = sr.ReadToEnd(); // DON'T DO THIS IN PROD!

    string contentType = Request.ContentType;

    // Content-Type can have the format: application/json; charset=utf-8
    // Hence, we need to do some substringing:
    int index = contentType.IndexOf(';');
    if(index > 0)
        contentType = contentType.Substring(0, index);
    contentType = contentType.Trim();

    // Now you can call your custom deserializers.
    if (contentType == "application/json")
    {
        T result = ServiceStack.Text.JsonSerializer.DeserializeFromString<T>(rawData);                
        return result;
    }
    else if (contentType == "text/xml" || contentType == "application/xml")
    {
        throw new HttpException(501, "XML is not yet implemented!");
    }
}

How to get server path of physical path ?

5 votes

I want to convert this physical path "C:\bla\bla\Content\Upload\image.jpg" to server path like "/Content/Upload/image.jpg".

How can i do that ?

you can use something like that :

 public static class Extensions        {
        public static string RelativePath(this HttpServerUtility utility, string path, HttpRequest context)
        {
            return path.Replace(context.ServerVariables["APPL_PHYSICAL_PATH"], "/").Replace(@"\", "/");
        }
    }

and you call

Server.RelativePath(path, Request); 

How to create an empty Listbox and pass the options without selecting them?

5 votes

In my form I'm moving categories from one listbox to another like this:
enter image description here

The bottom box is the "input" box that is read on the server side when the form is posted. Here's how I create the listbox:

<%: Html.ListBoxFor(m => m.categories, Model.categories)%>

I'm having two problems here:

  1. In Firefox, when the form is loaded for the first time the bottom box always has a default <option></option>. Is it possible to remove this on server side? IE seem to create an empty box but not FF.
    To solve this I'm removing the empty option on page load. One problem with this is that when a form has an error and isn't submitted, the options are removed again.

  2. In order for the options in the bottom box to be posted they have to be selected. To solve this I've used the jQuery below to select the options on form post.


jQuery to select options on submit:

$("form").submit(function (event) {
    $("#categories").find("option").attr('selected', 'selected');  
});

jQuery to delete option on load:

$("#categories").find("option").remove();

QUESTIONS
1. Can I create an empty listbox that work in all browsers?
2. Do I have to select the options in the bottom box or is there a workaround?

Clarifiation: I'd like to have as much as possible done on server side, preferably with something related to MVC.

1: Instead of removing all options just remove empty ones, this way it wont reset.

$('#mySelect option').each(function () {
    if(!$(this).val())
        $(this).remove();
});

http://jsfiddle.net/yWHLW/5/

Why can't Asp.net MVC distinguish between two actions when they have different parameters?

5 votes

I am trying to have two different methods for account registration in my Asp.net MVC application, one for general users to register for and another for users who are registering with a specific registration token. Thus I have the following method signatures in my AccountController:

public virtual ActionResult Register () {...}

public virtual ActionResult Register (Guid registrationToken) {...}

However, when I go to http://localhost/Account/Register I get an exception that the current request is ambiguous between these two actions. I was under the impression that it would use the parameterless Register action if there was no registrationToken GET parameter passed in, otherwise it would use the 2nd.

Does this require special route configuration?

Would it be easier to have one method with a nullable parameter? This will also automatically solve your problem as it will not be ambiguous anymore:

public virtual ActionResult Register (Guid? registrationToken)
{
    if(registrationToken.HasValue)
    {
         // this is specific user
    }         
    else
    {
         // this is general user
    }
}