MVC using methods from a helpers namespace - c#

I have the following in ~/Helpers/Helpers.cs:
namespace AdjusterSave.Helpers
{
public class Helpers : Controller
{
// various methods such as the following...
public void GetDropdowns()
{
}
}
}
I am trying to use these in my ~/Controllers/AdjusterController.cs file by including it like so:
using AdjusterSave.Helpers;
However, I continue to get the following error when trying to use the methods. When I call this:
GetDropdowns();
I get this error:
The name 'GetDropdowns' does not exist in the current context.
Edit:
Trying to use method like so (in ~/Controllers/AdjusterController.cs):
public ActionResult ViewProfile()
{
// a bunch of code like this:
User user = db.Users.Where(x => x.username == HttpContext.User.Identity.Name).FirstOrDefault();
AdjusterViewProfileInfo model = new AdjusterViewProfileInfo();
// get name
model.namePrefix = user.namePrefix;
model.firstName = user.firstName;
model.middleInitial = user.middleInitial;
model.lastName = user.lastName;
model.nameSuffix = user.nameSuffix;
// end then, finally,
GetDropdowns();
// followed by...
TempData["CurrentPage"] = "ViewProfile";
return View("", _layout, model);
}
Edit:
GetDropdowns Example:
public void GetDropdowns(this Controller controller)
{
// get name prefixes
List<SelectListItem> prefixList = new List<SelectListItem>();
prefixList.Add(new SelectListItem { Value = "Mr.", Text = "Mr." });
prefixList.Add(new SelectListItem { Value = "Mrs.", Text = "Mrs." });
prefixList.Add(new SelectListItem { Value = "Ms.", Text = "Ms." });
ViewBag.PrefixList = new SelectList(prefixList, "Value", "Text");
}

You are doing it wrong. What you need to do is to create a static class like this:
public static class Helpers
{
public static void GetDropdowns(this Controller controller)
{
// var username = controller.HttpContext.User.Identity.Name;
// get name prefixes
List<SelectListItem> prefixList = new List<SelectListItem>();
prefixList.Add(new SelectListItem { Value = "Mr.", Text = "Mr." });
prefixList.Add(new SelectListItem { Value = "Mrs.", Text = "Mrs." });
prefixList.Add(new SelectListItem { Value = "Ms.", Text = "Ms." });
controller.ViewBag.PrefixList = new SelectList(prefixList, "Value", "Text");
}
}
And, you can use it in your Controller like this:
this.GetDropdowns();

If you want to call GetDropdowns() you can:
Instantiate Helpers and call it:
new Helpers().GetDropdowns();
Make method GetDropdowns static:
public static void GetDropdowns()
{
}
and then call it:
Helpers.GetDropdowns();
You may also inherit AdjusterController from Helpers:
public class AdjusterController : Helpers
{
}
and then call it just as you did. Everything depends on what you're interested in. I guess you should not inherit Helpers from Controller and make the method static, but it's just a guess.

You can use the Extension Methods instead inheriths from Controller:
public static class Helpers
{
public static void GetDropdowns(this Controller controller)
{
// do something with the "controller", for sample:
controller.ViewBag = new List<string>();
}
}
Everything you need to access on the controller you can do by the controller parameter.
And in your controller you can do something like this:
public ActionResult Index()
{
// just call it, and the .net framework will pass "this" controller to your extension methodo
GetDropdowns();
}

Related

Calling function from BLL layer to controller in MVC5

public class StudentBLL
{
StudentDAL objStudent = new StudentDAL();
public List<StudentDAL> GetAllStudnets() {
List<StudentDAL > lstStudents = objStudent.GetStudentList().Tables[0].AsEnumerable().Select(
dataRow => new StudentDAL
{
StuID = dataRow.Field<int>("StudentId"),
StuName = dataRow.Field<int>("StudentName")
}).ToList();
return lstStudents;
}
}
I want to call this function in my Home Controller:
public JsonResult LoadStudents(int randomJunk)
{
//call function here ??
List<SelectListItem> selectListItems = new List<SelectListItem>();
//selectListItems.Add(si);
// selectListItems.Add(si1);
var notesTypes = new SelectList(selectListItems, "Value", "Text");
return Json(notesTypes, JsonRequestBehavior.AllowGet);
}
So how can call the return list to my Home Controller , I'm really confused and I'm not a student
Create an object of class StudentBLL and call the method GetAllStudnets with this object
StudentBLL obj = new StudentBLL ();
List<StudentDAL> ls = obj.GetAllStudnets();
Best practise is to create an interface with the required methods. create a class which implements the method. Use dependency injection to inject the class in the controller to call the method.

how to customize Html Helper to act according to the question Type?

I made a survey application like the following design:
Survey: ID,Name.
Question: ID,SurveyId,QuestionText,QuestionTypeId.
QuerstionType can be (Text, CheckBox, DropDown,RadioButton).
What's the best practice to give each question a suitable Html Helper at run time.
currently I am using traditional if else statements.
if(QuestionModel.QuestionTypeId==QuestionTypes.Text)
{
#Html.editor()
}
else if(QuestionModel.QuestionTypeId==QuestionTypes.DropDown)
{
#Html.DropDownList()
}
else
{
...
}
and so on.
I feel that I making something wrong, is there any way to customize one html helper to act differently according to the question Type.
Or if I can attach the html helper to a view model, and use it directly in the view like this:
Model.CustomDropdown.
You can create a custom Html Helper component like this :
namespace System.Web.Mvc
{
public static partial class HtmlHelperExtensions
{
public static MvcHtmlString CustomComponent(this HtmlHelper helper, string QuestionTypeId)
{
if (QuestionTypeId == "Text")
{
var inputTag = new TagBuilder("input");
inputTag.MergeAttribute("type", "text");
return MvcHtmlString.Create(inputTag.ToString());
}
else if (QuestionTypeId == "DropDown")
{
var dropDownTag = new TagBuilder("select");
dropDownTag.MergeAttribute("type", "text");
var option = new TagBuilder("option");
option.InnerHtml = "Option 1";
option.MergeAttribute("value", "option1");
dropDownTag.InnerHtml += option.ToString();
option = new TagBuilder("option");
option.InnerHtml = "Option 2";
option.MergeAttribute("value", "option2");
dropDownTag.InnerHtml += option.ToString();
return MvcHtmlString.Create(dropDownTag.ToString());
}
else
{
var inputTag = new TagBuilder("input");
inputTag.MergeAttribute("type", "checkbox");
return MvcHtmlString.Create(inputTag.ToString());
}
}
}
}
And in your Razor code You can call it like :
#Html.CustomComponent("Text")
#Html.CustomComponent("DropDown")
#Html.CustomComponent("Check")
In your case while creating the component, You have to pass your Custom Object in parameter instead of string. Also, while calling you will have to pass that custom object. Like :
public static MvcHtmlString CustomComponent(this HtmlHelper helper, QuestionModel questionModel)
{
if (questionModel.QuestionTypeId==QuestionTypes.Text)
{
var inputTag = new TagBuilder("input");
inputTag.MergeAttribute("type", "text");
return MvcHtmlString.Create(inputTag.ToString());
}
}
And in your Razor :
#Html.CustomComponent(questionModelObject)

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
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();
}
}
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>();
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;
}

Adding item to the List<T>

I am probably doing something silly but cannot find out what. I am trying to modify simple membership functionality in ASP.NET MVC 4. I have slightly modified a RegisterModel coming with the template, and added a list of categories to it like so:
public class RegisterModel
{
...
public List<SelectListItem> Categories { get; set; }
}
Then in the account controller I'm trying to add an item to this list but get "Object reference not set to an instance of an object." error:
[AllowAnonymous]
public ActionResult Register()
{
RegisterModel rm = new RegisterModel();
//SelectListItem guestCategory = new SelectListItem();
//guestCategory.Value = null;
//guestCategory.Text = "Guest";
rm.Categories.Add(new SelectListItem { Value = null, Text = "Guest" });
...
Any ideas why?
you just need to do this before adding items to list , because when you add items its not get instantiated that why its giving error
rm.Categories = new List<SelectListItem>();
that means in this method do like this
[AllowAnonymous]
public ActionResult Register()
{
RegisterModel rm = new RegisterModel();
rm.Categories = new List<SelectListItem>();//added line
rm.Categories.Add(new SelectListItem { Value = null, Text = "Guest" });
...
or
you can do same thing in constructor of RegisterModel .
public class RegisterModel
{
public RegisterModel
{
Categories = new List<SelectListItem>();//added line
}
In your class constructor initialize the list
public class RegisterModel
{
RegisterModel()
{
Categories = new List<SelectListItem>();
}
......
Since you are using an auto-implemented property {get;set;} you have to initialize it in the constructor. If you don't want to do in the Constructor then you can do:
public class RegisterModel
{
    ...
private List<SelectListItem> _Categories = new List<SelectListItem>();
private List<SelectListItem> Categories
{
get { return _Categories; }
set { _Categories = value; }
}
}
You can also initialize the List with the object, before using it.
RegisterModel rm = new RegisterModel();
r.Categories = new List<SelectListItem>(); // like that
rm.Categories.Add(new SelectListItem { Value = null, Text = "Guest" });
But its better if you initialize the list in constructor or through a private field (if not using auto-implemented property), Because then you don't have to initialize a property of the object of Class RegisterModel, with each object creation.
You never initialized Categories to anything. It is null.
Initialize it to an empty list to avoid the error, preferably in the constructor:
Categories = new List<SelectListItem>();

Set selected value in dropdown list

How do I set the selected value on a drop down list? Here is what I have so far:
#model Web.Models.PostGraduateModels.PlannedSpecialty
#Html.DropDownList("PlannedSpecialtyID")
//controller
[HttpGet]
public PartialViewResult PlannedSpecialty()
{
// Get Planned Specialty ID
var pgtservice = new PgtService();
PostGraduateModels.PlannedSpecialty plannedSpecialty = pgtservice.GetPlannedSpecialtyId();
// Get Data for Planned Specialty DropDown List from SpecialtyLookup
var pgtServ = new PgtService();
var items = pgtServ.GetPlannedSpecialtyDropDownItems();
ViewBag.PlannedSpecialtyId = items;
return PartialView(plannedSpecialty);
}
// service
public IEnumerable<SelectListItem> GetPlannedSpecialtyDropDownItems ()
{
using (var db = Step3Provider.CreateInstance())
{
var specialtyList = db.GetPlannedSpecialtyDdlItems();
return specialtyList;
}
}
// data access
public IEnumerable<SelectListItem> GetPlannedSpecialtyDdlItems()
{
IEnumerable<Specialty> specialties = this._context.Specialties().GetAll();
var selList = new List<SelectListItem>();
foreach (var item in specialties)
{
var tempps = new SelectListItem()
{
Text = item.Description,
Value = item.Id.ToString()
};
selList.Add(tempps);
}
return selList;
}
I would recommend you to avoid using ViewBag/ViewData/ Weekly typed code. Use strongly typed code and it makes it more readable. Do not use the Magic strings/ Magic variables. I would add a collection property to your ViewModel to hold the SelectList items and another property to hold the selected item value.
public class PlannedSpecialty
{
public IEnumerable<SelectListItem> SpecialtyItems { set;get;}
public int SelectedSpeciality { set;get;}
//Other Properties
}
and in your Get action, If you want to set some Item as selected,
public PartialViewResult PlannedSpecialty()
{
var pgtServ = new PgtService();
var vm=new PlannedSpecialty();
vm.SpecialtyItems = pgtServ.GetPlannedSpecialtyDropDownItems();
//just hard coding for demo. you may get the value from some source.
vm.SelectedSpeciality=25;// here you are setting the selected value.
return View(vm);
}
Now in the View, use the Html.DropDownListFor helper method
#Html.DropDownListFor(x=>x.SelectedSpeciality,Model.SpecialtyItems,"select one ")
Use the selected property of the SelectListItem class:
selList.Selected = true;

Categories