ASP.NET MVC - Having trouble obtaining pull-down selection in control - asp.net-mvc

I am having trouble accessing a user's pull-down selection from within the controller once the user has selected a value and submitted it via the view.
The pull-down menu is populating correctly and I've written a simple JavaScript function that alerts the user when a selection change is made. Via the alert, I see the RoleID value. I just can't seem to access it in the controller. Please see my code below and help! Thank you in advance.
Model:
public class dbModels
public class UserAccessRequestViewModel
{
dbEntities _dbEntities = new dbEntities();
public IEnumerable<ActiveRoles> Roles { get; set}
public Guid selectedRoleID { get; set:}
public class ActiveRoles
{
public Guid RoleID { get; set; }
public string RoleName { get; set; }
}
public List<ActiveRoles> GetActiveRoles()
{
var ActiveRoles = dbEntities.LU_ROLE.Where(x => x.ACTIVE)
.Select (x => new ActiveRoles { RoleID = x.ROLE_ID, RoleName = x.ROLE_NAME }).ToArray();
return activeRoles.ToList();
}
}
View:
<div class="text-left" style="margin:4px; padding:4px">
<h2>Assign Role</h2>
#Html.DropDownList(model => model.selectedRoleID, new SelectList(Model.Roles, "RoleID", "RoleName"), new { #onchange = getUserRoleID(this)" })
</div>
<div class="form-actions no-color" style="margin:4px; padding:4px">
#using (Html.BeginForm("Approve", "UserAccessRequestManagement", FormMethod.Post))
{
<input type="submit" value="Approve" class="btn btn-default" />
}
#Html.ActionLink("Back to List", "Index")
</div>
Control:
public class UserAccessRequestManagementController : Controller
dbModels.UserAccessRequestViewModel _UserAccessRequestViewModel = new dbModels.UserAccessRequestViewModel();
[HttpPost, ActionName("Approve")]
public ActionResult Approve(Guid id)
{
Guid RoleID = _UserAccessRequestViewModel.selectedRoleID;
}

Your select input should be part of your form.
<div class="form-actions no-color" style="margin:4px; padding:4px">
#using (Html.BeginForm("Approve", "UserAccessRequestManagement", FormMethod.Post))
{
<div class="text-left" style="margin:4px; padding:4px">
<h2>Assign Role</h2>
#Html.DropDownList(model => model.selectedRoleID, new SelectList(Model.Roles, "RoleID", "RoleName"), new { #onchange = getUserRoleID(this)" })
</div>
<input type="submit" value="Approve" class="btn btn-default" />
}
#Html.ActionLink("Back to List", "Index")
</div>
Also you have to make sure what you want to get in your Controller action as a parameter.
If you just need a guid then change the parameter name to selectedRoleID as the name of the input element should match with your action parameter. In case you want to take entire model as parameter then you have to mention it correctly in action defintion.
In case you want to get entire model in your POST action
public class UserAccessRequestManagementController : Controller
dbModels.UserAccessRequestViewModel _UserAccessRequestViewModel = new dbModels.UserAccessRequestViewModel();
[HttpPost, ActionName("Approve")]
public ActionResult Approve(UserAccessRequestViewModel model)
{
Guid RoleID = model.selectedRoleID;
}
OR make it like this In case you just want a selected guid in your POST action
[HttpPost, ActionName("Approve")]
public ActionResult Approve(Guid selectedRoleID)
{
Guid RoleID = selectedRoleID
}

Related

html helper #enumdropdownlistfor is not sending the value to the model

enumdropdownlist is used only with strings not integers.
i want to show admin management in dropdown in view.
if user select admin background value of admin which is 1 send to the model
if user select management background value of manage which is 2 send to the model.
enumdropdownlist is coming with string not integers.
I want model which is come with integers
hope anyone understand.
see this is my model
public class tbl_Login
{
public string userid { get; set; }
public string pass { get; set; }
public string Phone { get; set; }
public roles userrole { get; set; }
}
public enum roles
{
Management,
Admin
}
this is is my view.
#using (Html.BeginForm("Login", "Account", FormMethod.Post))
{
<div class="form-group has-feedback">
#Html.EnumDropDownListFor(Model => Model.userrole,"Select",new { #class =
"form-control" })
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="col-xs-4">
<input type="submit" value="Sign In" class="btn btn-primary btn-block btn-
flat" />
</div>
}
instead of asp.net code
<select class="form-control">
<option>--Select--</option>
<option>Admin</option>
<option>Management</option>
</select>
finally this is my controller.
// I want this controller with log come with value i.e admin=1 or management=2.
public ActionResult Login(tbl_Login log)
{
string uri = Request.Url.AbsoluteUri;
SqlConnection con = new SqlConnection(constring);
SqlDataAdapter adp = new SqlDataAdapter();
if (log.userrole == 'Admin')
{
...
}
return View();
}
I want to compare this in controller
if(log.userrole==1)
{
}
EDIT:
In your controller you can do this:
if ((int)role == 1)
{
// your logic here ...
}
Some information about Enums and how you can handle them:
Cast an integer value to a Enum like this:
roles role = (roles)yourIntValue;
Or like this
roles role= (roles)Enum.ToObject(typeof(roles) , yourIntValue);
From a string you could do something along these lines:
roles role= (roles) Enum.Parse(typeof(roles), yourStringValue);

MVC BeginCollectionItem

I'm having some issue getting my partial view BeginCollectionItem to save to the database. I have a form which has a dynamic number of "sections" that can be added to the page, and within each of these fields there is a text box where the user can enter the section name.
As far as I can tell the BeginCollectionItem within the partial view is working properly, however I cannot post the info to the database. In my other forms I have used a [bind()] to send the data to the database, is it possible to get this into a list and then post that via a bind?
I've included my code below:
The Model:
namespace project.Models.SetupViewModels
{
public class SOPTopTemplateBuilderViewModel
{
public List<Section> Section { get; set; }
}
public class Section {
public int SectionId { get; set; }
public string SectionText { get; set; }
public string TopTempId { get; set; }
}
}
cshtml:
#model IEnumerable<project.Models.SetupViewModels.Section>
#using (Html.BeginForm("SOPTopTemplateBuilder", "Setup", FormMethod.Post))
{
<div class="main-holder" id="theform">
#foreach(var item in Model)
{
#Html.Partial("_SectionCreator", item)
}
</div>
<button id="add" type="button">Add</button>
<div class="form-group submit-row">
<div class="col-12 float-to-right">
<input type="submit" class="btn btn-default" value="continue" />
</div>
</div>
}
#section Scripts {
<script>
$(document).ready(function () {
var url = '#Url.Action("AddSection")';
var form = $('form');
var recipients = $('#theform');
$('#add').click(function() {
$.post(url, function(response) {
recipients.append(response);
// Reparse the validator for client side validation
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
});
});
</script>
}
Partial View:
#model project.Models.SetupViewModels.Section
#using HtmlHelpers.BeginCollectionItemCore
#using (Html.BeginCollectionItem("Section"))
{
<div class="new-section">
<div>
<p>New Section</p>
#Html.HiddenFor(m => m.SectionId, new { #class="id" })
#Html.EditorFor(m => m.SectionText, new { #class = "form-control limit-form"})
</div>
</div>
}
Controller:
[HttpPost]
public PartialViewResult AddSection()
{
return PartialView("_SectionCreator", new Section());
}
[HttpGet]
public ActionResult SOPTopTemplateBuilder(){
List<Section> model = new List<Section>();
return View(model);
}
[HttpPost]
public ActionResult SOPTopTemplateBuilder(IEnumerable<Section> soptop)
{
if (ModelState.IsValid)
{}
return View(soptop);
}
Your use of Html.BeginCollectionItem("Section") perpends Section[xxxx] to the name attribute (where xxxx is a Guid) so that you generating inputs with
<input name="Section[xxxx].SectionId" .... />
which posts back to a model containing a collection property named Sections.
Since you already have a model with that property, you can change the POST method to
[HttpPost]
public ActionResult SOPTopTemplateBuilder(SOPTopTemplateBuilderViewModel soptop)
other options include
Using your existing POST method and omitting the "Section" prefix
using Html.BeginCollectionItem("") which will generate
name="[xxxx].SectionId"
Changing the POST method signature to public ActionResult
SOPTopTemplateBuilder(IEnumerable<Section> section) (where the
name of the parameter matches the name of the prefix)
Using a BindAttribute to 'strip' the prefix from the form values
public ActionResult SOPTopTemplateBuilder([Bind(Prefix = "Section")]IEnumerable<Section> soptop)
As a side note, your editing data, so you should always use a view model (say public class SectionViewModel) rather than using data models in your view. - What is ViewModel in MVC?

using (Html.BeginForm()) on button submit to send an object of type CategoriesLanguages

Hello as I'm so new to Mvc I woild appreciate any Help!
So Here is myModels
Category
-CategoryID
-DateCreated
CategoriesLanguages
ID (autoincrement)
CategoryID
LanguageID
Title
Description
Basically I want to be able when I click AddNew Button - I create a new record in Category table - and I'm having the id of the created category.
And in the Create() view which Create() action is returning I gave the user opportunity to fill the description and title of categorylanguages.
ANd when the user clicks the submit button he should be redirected to Create(CategoryLanguages) acton which as you see accepts an object of CategoryLanguage and this action will simply store this object in the database. My QUESTION IS HOW TO RETURN this object!
public class CategoryController : Controller
{
public ActionResult Create()
{
CategoryViewModel vm = new CategoryViewModel();
vm.AddNewCategory();
return View(vm);
}
pubcli AcrionResult Create(CategoryLanguage ob)
{
CategoryViewModel vm = new CategoryViewModel();
vm.SaveInDatabaseCategorylanguage(ob);
return RedirectToAction("Index");
}
}
And Here is my View CreateView.csHtml
#model MvcApplication1.ViewModel.CategoryViewModel
/
#using (Html.BeginForm())
{
<fieldset class="form-horizontal">
<legend>Category</legend>
// Here i should have a dropdpwn and teh selected value I should get it for LanguageID
<div class="control-group">
#Html.LabelFor(model => model.modelcatlang.Title, new { #class = "control-label" })
<div class="controls">
#Html.EditorFor(model => model.modelcatlang.Title) //From here i should get title
</div>
</div>
<div class="control-group">
#Html.LabelFor(model => model.modelcatlang.Description, new { #class = "control-label" })
<div class="controls">
#Html.EditorFor(model => model.modelcatlang.Description) //from here I should get the description
</div>
</div>
<div class="form-actions no-color">
<input type="submit" value="Create" class="btn" />
/*somehow ewhen i click this button I should make
CategoryLanguage catlang= new CategoryLanguahe;
catLang.CatID = insertedID (I have it nio problem);
catlang.lanID = dropdown.value;
catlang.Title = from title from editorform
...*/
</div>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
EDIT
I'm posting the code for My CategoryViewModel
public class CategoryViewModel
{
public CategoryLanguages modelcatlang { get; set; }
public int newCategoryID { get; set; }
public List<Language> lstLanguages { get; set; }
public List<CategoryLanguages> lstCategoryLanguages { get; set; }
public CategoryLanguages categoryToEdit { get; set; }
private readonly ICategoryRepository catRep;
private readonly ILanguageRepository lanRep;
private readonly ICategoryLanguageRepository catlanRep;
public CategoryViewModel()
: this(new CategoryRepository(), new LanguageRepository(), new CategoryLanguageRepository())
{
}
public CategoryViewModel(ICategoryRepository catRep, ILanguageRepository lanRep, ICategoryLanguageRepository catlanRep)
{
this.catRep = catRep;
this.lanRep = lanRep;
this.catlanRep = catlanRep;
}
public void AddNewCategory()
{
lstLanguages = lanRep.GetAllAvailableLanguages();
newCategoryID = catRep.AddCategory();
modelcatlang = new CategoryLanguages();
}
So in the ViewModel in AddNewCategory() Method i have the id of the just inserted Category in category table (in newCategoryID)
I also make an instance of CategoryLanguage().SO maybe my new question will be - how can i fill all the properties of modelcatlang object(part of my viewmodel) and return it to Create(CategoriesLanguages) action

Retrieving values from partial view during post method

I have a view which contains a dropdown list and on dropdownlist item being selected I load a partial view. And when the form is submitted I want to be able to get both the values from main view and partial view during form submit.
Here is the main view
#model AdminPortal.Areas.Hardware.Models.CreateModule
#{
ViewBag.Title = "Create Module";
Layout = "~/Views/shared/_BootstrapLayout.basic.cshtml";
}
#Html.ValidationSummary(true)
<fieldset class="form-horizontal">
<legend>Add a Module <small>Create</small></legend>
#using (Html.BeginForm("CreateModule", "Module", new{id="AddModuleForm"}))
{
#Html.ValidationSummary(true)
<div class ="controls">
<div class="input-block-level">#Html.TextBoxFor(model => model.ModuleId, new {#placeholder = "ModuleID"})</div>
<br/>
<div class ="input-block-level" id="selectedModuleTypeName">#Html.DropDownListFor(model => model.SelectedModuleTypeName, Model.TypeNames,"Select Moduletype", new{id = "ModuleList"})</div>
<br/>
<div id="partialDiv"></div>
</div>
<div class="form-actions" id="buttons">
<button type="submit" class="btn btn-primary" id="Submit">Save changes</button>
#Html.ActionLink("Cancel", "ModuleList", null, new { #class = "btn " })
</div>
}
</fieldset>
<div>
#Html.ActionLink("Back to List", "ModuleList")
</div>
<script>
$("#buttons").hide();
$("#ModuleList").on("change", function() {
var modId = $(this).val();
$.get('#Url.Action("GetModulePropertyName", "Module")', { moduleTypeValue: modId }, function(result) {
$("#partialDiv").html(result);
});
//uncomment following section to check if the partial view is working properly
/*.done(function() { alert("done"); })
.fail(function() { alert("fail"); })
.always(function() { alert("completed"); });*/
});
$("#buttons").show();
</script>
and here is the partial view
#model IEnumerable<string>
#foreach(var names in Model)
{
<div class="input-block-level">#Html.TextBoxFor(m=>names, new{Value="", placeholder=names})</div>
<br/>
}
Here is my model
public class CreateModule
{
//Empty form to handle form serialization
public CreateModule()
{
}
[Required]
public string ModuleId { get; set; }
[DataType(DataType.DateTime)]
public DateTime DateEntered { get; set; }
[Required]
public string SelectedModuleTypeName { get; set; }
public IEnumerable<SelectListItem> TypeNames { get; set; }
public List<Property> Properties { get; set; }
}
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
Here is the method that script in main view forwards to
[HttpGet]
public ActionResult GetModulePropertyName(string moduleTypeValue)
{
var moduleKindId = _repository.GetModuleKindId(moduleTypeValue);
var modulePropertyNames = _repository.GetModuleKindPropertyNames(moduleTypeValue);
return PartialView("GetModulePropertyName",modulePropertyNames);
}
and finally here is httppost method for the main view
[HttpPost]
public ActionResult CreateModule(CreateModule moduleV)
{
var module = new Module
{
ModuleTypeId = Convert.ToInt64(moduleV.SelectedModuleTypeName),
ModuleId = moduleV.ModuleId,
DateEntered = moduleV.DateEntered,
};
if (ModelState.IsValid)
{
_repository.AddModule(module);
Success("Module added successfully!");
return RedirectToAction("ModuleList", "Module", new {area = "Hardware"});
}
Error("Something went wrong!");
return RedirectToAction("CreateModule", "Module", new { area = "Hardware" });
}
Current situation:
When the form is posted, the properties value of the model that is being passed via partial view is null. I get other values, like typename, Module ID.
What I'd want:
I also want to get the value of properties that is being passed via partial view.
You don't have any input field for the Properties property anywhere in your form. So it will always be null. That's normal.
Here's how you could proceed. Start by setting the correct navigational property so that the helper generates correct names of the corresponding input fields.
Also make sure that you are passing an IEnumerable<Property> model to the partial if you want to be able to get them back correctly:
[HttpGet]
public ActionResult GetModulePropertyName(string moduleTypeValue)
{
var moduleKindId = _repository.GetModuleKindId(moduleTypeValue);
IList<Property> model = ...
return PartialView("GetModulePropertyName", model.ToList());
}
and in your partial view use an editor template:
#model IList<Property>
#{
// This indicates the current navigational context to the helpers
ViewData.TemplateInfo.HtmlFieldPrefix = "Properties";
}
#Html.EditorForModel()
and the last step is to define a custom editor template for the Property class: ~/Views/Shared/EditorTemplates/Property.cshtml (note that the name and location of the template is important)
#model Property
<div class="input-block-level">
#Html.HiddenFor(m => m.Name)
#Html.TextBoxFor(m => m.Value, new { placeholder = Model.Name })
</div>
<br />
Try using the
List<Property>
as a model in your partial view and pass the CreateModule.Properties as model from your View
The problem is model binder can not figure out there
#Html.TextBoxFor(m=>names, new{Value="", placeholder=names})
belongs to as the "names" is not a property on your model class. If you need to bind to the CreateModule.Properties you need to change the partial view to emit textboxes with aproprate names, like this one:
#model IEnumerable<string>
#
{
int i=0;
}
#foreach(var names in Model)
{
<div class="input-block-level">#Html.TextBox("Properties[" + i + "].Value")</div>
<br/>
}

View is not sending right data to controller

I have a very simple partial view and I am using ajaxform. In my partial view I have one sigle textArea and a Submit button.
The problem is whatever I write into the text area, It does not send the data to controller, rather it sends a text which is = "Comment".
If I dont write anything, the validation works perfect.
The Viewmodel:
public class NoteCommentViewModel
{
public Int32 Id { get; set; }
[Required(ErrorMessage="Hey, if you dont wanna write then why pressing the button !!")]
public string Comment { get; set; }
public DateTime CommentDate { get; set; }
public long UserId { get; set; }
public double Rating { get; set; }
public Guid NoteId { get; set; }
}
Controller:
//
//GET:/Notes/Comment/
public ActionResult Comment(string id)
{
ViewBag.NoteId = id;
var m = new NoteCommentViewModel()
{
NoteId = new Guid(id),
UserId = Convert.ToInt64(Session["LoginUserId"].ToString()),
//Comment=""
};
return PartialView(m);
}
//
//POST:/Notes/Comment
[HttpPost]
public ActionResult Comment(NoteCommentViewModel nvm)
{
NoteRatingComments comment = new NoteRatingComments();
comment.Comment = nvm.Comment; // Here I always have "Comment", regardless whatever I write in the page.
comment.EntryDate = DateTime.Now;
comment.NoteId = nvm.NoteId;
comment.UserId = nvm.UserId;
comment.Rating = 3.00;
dc.NoteRatingComments.AddObject(comment);
dc.SaveChanges();
return Content(Boolean.TrueString);
}
The view:
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Ajax.BeginForm("Comment", "Notes", null, new AjaxOptions
{
UpdateTargetId = "Comment-message",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "commentSuccess"
}, new { id = "commentForm" }))
{
<div style="margin-top:20px;">
<div id="commentSuccess"></div>
<div class="comentPic">
#{
long UserId = Convert.ToInt64(Session["LoginUserId"].ToString());
string Fullname = Session["LoginUserFullName"].ToString();
}
<img src='https://graph.facebook.com/#UserId/picture' height="100px" width="100px"/>
</div>
<div class="commentText">
#Html.HiddenFor(m => m.UserId)
#Html.HiddenFor(m=>m.NoteId)
#Html.TextAreaFor(m => m.Comment, new { style = "width:600px;height:120px;" })
<br />
#Html.ValidationMessageFor(m => m.Comment)
<div style="text-align:right;">
<input type="submit" value="Comment" name="comment" class="btn"/>
</div>
</div>
<div class="clear"></div>
</div>
}
Here is the screen shot of the error...for better understanding. I am writing "data" in the view but in the controller I am getting "Comment"..Where is it coming from??
WOuld be great if someone can help me to identify the problem...!!
The problem is that your submit button's name attribute is the same as the Comment textarea name attribute.
To resolve this you need to change the submit button's name to something else than "comment" or remove the name attribute from your submit button, so change:
<input type="submit" value="Comment" name="comment" class="btn"/>
To
<input type="submit" value="Comment" class="btn"/>
Because the Ajax.BeginForm uses the the jQuery .serializeArray() method which - because your submit button has a name and this input triggers the submit - also sends the submit button's value "Comment" to the server.
I am not sure what exactly your problem is. But the below code should work.
public class NoteCommentViewModel
{
public Int32 Id { get; set; }
[Required(ErrorMessage=" Your Error message")]
[DataType(DataType.MultilineText)]
public string Comment { get; set; }
//other properties
}
And in your View, Use it like this
#Html.EditorFor(m => m.Comment)
actually your code is very confusing. in your view u didnt use Model and seems you use m as your model and as i know this is completely wrong.i dont know your view is rendering but wherever you use m=>m.sth the second m must be nothin.instead you must define your #model NoteCommentViewModel at first of cshtml file and then use Model instead of second m

Resources