Dhanil Dinesan
Dhanil Dinesan

Reputation: 575

Controller to controller communication in C# MVC

I want to use the list of state controller in a district controller. Are there any better ideas. I have tried one which is working

I put this code in the district controller by using constructor injection.

In this case, the entire code needs to be placed in the district controller. Is there any way to reduce the code. A better way?

   #region StateDropDown
    public List<SelectListItem> StateDropDown()
    {
        List<SelectListItem> selectListItem = new List<SelectListItem>();
        List<StateViewModel> stateList = Mapper.Map<List<State>, List<StateViewModel>>(_stateBusiness.GetStateForSelectList());
        if (stateList != null)
            foreach (StateViewModel state in stateList)
            {
                selectListItem.Add(new SelectListItem
                {
                    Text = state.Description,
                    Value = state.Code.ToString(),
                    Selected = false
                });
            }
        return selectListItem;
    }
    #endregion StateDropDown

Upvotes: 3

Views: 1310

Answers (3)

Peter Riesz
Peter Riesz

Reputation: 3426

If you using core one option might be to keep this off the controller and use a TagHelper this will let you inject the options into the tag with a simple attribute state-items reducing controller dependencies and keeping this state off the ViewBag while being more reusable.

Here is how it wold look in the view:

<select asp-for="State" state-items />

The TagHelper:

[HtmlTargetElement("select", Attributes = "state-items")]
public class StateItemsTagHelper : TagHelper {
    private readonly StateBusiness _stateBusiness;

    [HtmlAttributeName("asp-for")]
    public ModelExpression For { get; set; }

    public StateItemsTagHelper(StateBusiness stateBusiness) {
        this._stateBusiness = stateBusiness;
    }

    public override void Process(TagHelperContext context, TagHelperOutput output) {
        content.TagMode = TagMode.StartTagAndEndTag;

        var value = For?.Model as string;

        var items = _stateBusiness.GetStateForSelectList()?.Select(state => new SelectListItem {
             Text = state.Description,
             Value = state.Code.ToString(),
             Selected = value == state.Code.ToString()
        })) ?? Enumerable.Empty<SelectListItem>();

        foreach(var item in items) {
            output.Content.AppendHtml(item.ToHtmlContent());
        }
    }
}

For reusability item.ToHtmlContent is an extension method:

public static IHtmlContent ToHtmlContent(this SelectListItem item) {
    var option = new TagBuilder("option");
    option.Attributes.Add("value", item.Value);
    if(item.Selected) {
        option.Attributes.Add("selected", "selected");
    }
    option.InnerHtml.Append(item.Text);
    return option;
}

Upvotes: 0

Doruk
Doruk

Reputation: 912

This is what the term 'reusability' is invented for. Place the code in another file and make calls to it from any number of controllers you want, like code below.

//StateBusiness.cs
public class StateBusiness
{
    public List<SelectListItem> GetStatesForDropdown()
    {
        //your logic here
        return new  List<SelectListItem>();
    }
}

//StateController.cs
public class StateController : Controller
{
    var state = new StateBusiness();

    public ActionResult Index()
    {
        //call your code here 
        var states = state.GetStatesForDropdown();
        //and do whatever you want
        ViewBag.states = states;
        return View();
    }
}

//DistrictController.cs
public class DistrictController : Controller
{
    var state = new StateBusiness();

    public ActionResult Index()
    {
        //call it from here just the same
        var states = state.GetStatesForDropdown();
        ViewBag.states = states;
        return View();
    }
}

Upvotes: 1

fqhv
fqhv

Reputation: 1201

I don't know about better, but you could shorten this considerably using linq Select.

Mapper.Map<List<State>, List<StateViewModel>>(_stateBusiness.GetStateForSelectList())?
    .Select(state => new SelectListItem
    {
         Text = state.Description,
         Value = state.Code.ToString(),
         Selected = false
    }))?.ToList() ?? List<SelectListItem>();

Upvotes: 0

Related Questions