4

Is there an easy way to remove the use of Magic Strings when creating a SelectList, like in this example:

@Html.DropDownListFor( model => model.FooValue, new SelectList( Model.FooCollection,  "FooId", "FooText", Model.FooValue) )

The magic strings being "FooId" and "FooText"

The rest of the example is defined as follows:

//Foo Class
public class Foo {

  public int FooId { get; set; }
  public string FooText { get; set; }

}    

// Repository
public class MsSqlFooRepository : IFooRepository {

  public IEnumerable<Foo> GetFooCollection( ) {

    // Some database query

  }

}

//View model
public class FooListViewModel {

  public string FooValue { get; set; }
  public IEnumerable<Foo> FooCollection { get; set; }

}

//Controller
public class FooListController : Controller {

  private readonly IFooRepository _fooRepository;

  public FooListController() {

    _fooRepository = new FooRepository();

  }

  public ActionResult FooList() {

    FooListViewModel fooListViewModel = new FooListViewModel();

    FooListViewModel.FooCollection = _fooRepository.GetFooCollection;

    return View( FooListViewModel);

  }

}

3 Answers 3

3

Using an extension method and the power of lambda expressions, you can do this:

@Html.DropDownListFor(model => model.FooValue, Model.FooCollection.ToSelectList(x => x.FooText, x => x.FooId))

The extension method is as follows:

public static class SelectListHelper
{
    public static IList<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, string> text, Func<T, string> value)
    {
        var items = enumerable.Select(f => new SelectListItem()
        {
            Text = text(f),
            Value = value(f)
        }).ToList();
        items.Insert(0, new SelectListItem()
        {
            Text = "Choose value",
            Value = string.Empty
        });
        return items;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

I use View Models so I have the following properties for my FooValues dropdown:

public SelectList FooValues { get; set; }
public string FooValue { get; set; }

and then in my code for building my view model I do:

viewModel.FooValues = new SelectList(FooCollection, "FooId", "FooText", viewModel.FooValue);

Then in my view:

@Html.DropDownListFor(m => m.FooValue, Model.FooValues)

I hope this helps.

7 Comments

That just creates the same problem only the 'Magic Strings' have now moved to the View Model instead of the view.
The 'Magic String' problem is such that when compiled if "FooId" has become "FooFooId" it will not be picked up as an error until runtime.
Also if your view model has a value of type SelectList the second conversion is pointless.
I would have public IEnumerable<Foo> FooCollection { get; set; } in the view model then convert to what is required in the view. I am not then tied to a SelectList.
Also if your view model has a value of type SelectList the second conversion is pointless as I would return the data from the repository already as a selectlist. (Sorry I pressed enter before I had finished Typing )
|
0

In C# 6 you can take advantage of nameof and easily get rid of these magic strings.

... = new SelectList(context.Set<User>(), nameof(User.UserId), nameof(User.UserName));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.