How can we get the Id of an item inside the controller? - c#

So basically as the title said, currently working on a MVC5, how can I get the Id of the list of Items that I have in view of the controller? By a button click, I'm calling an action which doesn't have a view but requires the Id of the item, which is resulting in a NULL.
I read this article but they don't seem to work for me:
How to get the current user in ASP.NET MVC
public ActionResult GetItem(int Id)
{
Item item = new Repository().GetId(Id);
..
}

Okay, so after a discussion on the requirement, the following changes were required to be made on the View:
<div class="col-lg-4">
<a href="#Url.Action("GetItem", "Upload", new { id = Model.id}"">
</a>
<P>#p.Path</P>
</div>
And the Controller:
public ActionResult GetItem(int id)
The URL for each item would be generated uniquely based on the Model.id

Related

How to pass a parameter to controller through view?

I am trying to pass an ICollection argument through a view to the TeamMemberController.
I use SQL database with ASP.NET Core
The database is stored locally. When clicking the red marked button there should appear a new page containing a list of the team members. The TeamMembers are currently displayed to the left of the marked button. The view button should send the parameter and direct us to the teamMemberpage
But as you can see, the list appears to be empty
I have tried looking at the network in my browser and it gives me this:
Query String Parameters(1) :teamMembers: System.Collections.Generic.List`1[BugTracking.Data.Entities.TeamMember]
Video demonstrating issue
https://youtu.be/dJbloxDCeok
Code:
Project Index View
#foreach (var item in Model) {
<a asp-action="ShowTeamMembers"
asp-controller="TeamMember"
asp-route-teamMembers="#item.TeamMembers" class="btn btn-
secondary">view</a>
}
TeamMemberController
public class TeamMemberController : Controller
{
private readonly DatabaseContext _context;
public TeamMemberController(DatabaseContext context)
{
_context = context;
}
// GET: TeamMembers
public async Task<IActionResult> Index()
{
return View(await _context.TeamMembers.ToListAsync());
}
public IActionResult ShowTeamMembers(ICollection<TeamMember> teamMembers)
{
return View(nameof(Index), teamMembers);
}
}
The anchor tag will generate a url link to the given Controller/Action. Thus, it can only contain parameters that can be contained in the url of the link. So you cannot pass an object through on the url.
Try passing the Id of the team member
Project Index View
#foreach (var item in Model) {
<a asp-action="ShowTeamMembers"
asp-controller="TeamMember"
asp-route-Id="#item.TeamMembers.ID" class="btn btn-
secondary">view</a>
}
TeamMemberController
public IActionResult ShowTeamMembers(int Id)
{
var team = _context.TeamMembers.Where(team => team.ID == Id).FirstOrDefault()
return View(nameof(Index), team);
}
I solved the problem by sending the id of the project itself, instead of trying to send the List.
I could then from the TeamMemberController handle that object and take bind the list to a variable.
Code:
Project Index View
<a asp-action="ShowTeamMembers"
asp-controller="TeamMember"
asp-route-Id="#item.Id" class="btn btn-secondary">view</a>
TeamMemberController
public IActionResult ShowTeamMembers(Guid Id)
{
Project? project = _context.Projects.Include(p => p.TeamMembers).Where(p => p.Id == Id).FirstOrDefault();
List<TeamMember> team = project?.TeamMembers ?? new();
return View(nameof(Index), team);
}

How to keep click event dynamically created buttons in mvc

i have retrive name of buttons from database those button when i click a
button i need to show the some report.now i have everything is done.i
need to know how keep unique id for those buttons and how they worked
when i click button i need to show report in a separate page...
[HttpGet]
public ActionResult Estate()
{
return View("Estate", new EstateFunc().Estates());
}
[HttpPost]
public ActionResult Estate(int id=0)
{
if(id>0)
{
}
return View();
}
With MVC
View:
#foreach (var item in Model)
{
<tr>
<td>#item.Something...</td>
<td>#item.AnotherThing</td>
<td>
</td>
</tr>
}
This Razor code will generate as many button as the count of the collection items in your model. Every item in the collection should have unique ID and as you see we put this ID as parameter. So when the user clicks on any of the buttons, the unique ID will tell us which button was clicked (and to which item we should refer to)
Controller:
public ActionResult MyAction(int id = 0)
{
var model = ReportViewModel(id);
return ReportView(model);
}
private ReportViewModel(int id)
{
// Get Report from Database Where Id = id
// Populate ViewModel from the database data
// Return reportViewModel;
}
EDIT (adding example based on your code)
#foreach (var item in Model)
{
<div class="floated">
<a href="#Url.Action("MyAction", "MyController", new { Id = item.Id })"
class="Estates_button">#item.EstateName</a>
</div>
}

drop down list value is null after posting to controller in ASP.NET MVC

I am new to ASP.NET MVC. I have a simple form with a submit button and an html select element, populated with two items. When the form posts to my controller, all the form values are null. I've even tried doing it with $.POST instead and the id variable I am sending is null when it gets to the controller. Here is my code:
HTML
#using (Html.BeginForm("SetOptionForUser", "MyController", FormMethod.Post, new { #class="form-inline" }))
{
#Html.AntiForgeryToken()
<div class="text-center">
<div class="form-group">
<select id="ddlSelect" class="form-control">
#foreach (var item in Model.Persons)
{
<option value="#item.Id">#item.Name</option>
}
</select>
</div>
<button type="submit" class="btn btn-primary" id="btnEnter">Go</button>
</div>
}
MVC Controller
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult SetOptionForUser(FormCollection form)
{
string option = form["ddlSelect"].ToString(); //null error
return RedirectToAction("AnotherAction", "AnotherController");
}
It seems nothing in the form is being sent. I also tried this:
JS
$("#btnEnter").click(function (e) {
var optionId = $("#ddlSelect").val(); //this get val correctly
$.post(#Url.Action("SetOptionForUser", "MyController"), optionId);
});
MVC Controller for JS method
**MVC Controller**
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult SetOptionForUser(int optionId) //null
{
string option = optionId.ToString(); //null error
return RedirectToAction("AnotherAction", "AnotherController");
}
What I am doing wrong?
Normal form submit
Your normal form submit should work if your select element name and your http post action method parameter name is same.
<select name="selectedPerson" id="selectedPerson" class="form-control">
<!-- Options goes here -->
</select>
and your action method
[HttpPost]
public ActionResult SetOptionForUser(string selectedPerson)
{
string option = selectedPerson;
return RedirectToAction("AnotherAction", "AnotherController");
}
You might also consider using the Html.DropDownListFor or Html.DropDownList helper methods to generate the SELECT element from a list of items ( instead of manually writing the loop to render the option items).
Sending data with Ajax
Now if you want this to be ajaxified, you can send the data in either querystring or the request body
$(function(){
$("#btnEnter").click(function (e) {
e.preventDefault();
var optionId = $("#selectedPerson").val();
$.post('#Url.Action("SetOptionForUser", "MyController")', { selectedPerson:optionId});
});
});
Now there is no point in returning a RedirectResult for an ajax call. You might consider returning a json response (indicating whether your action was successful or not) from your action methodo and in the success callback of $.post you can inspect the value and do needed.
[HttpPost]
public ActionResult SetOptionForUser(string selectedPerson)
{
string option = selectedPerson;
return Json(new {status="success"});
}
And you can check the response in the callback
var optionId = $("#selectedPerson").val();
var url="#Url.Action("SetOptionForUser", "MyController")";
$.post(url, { selectedPerson:optionId}, function(response){
if(response.status==="success")
{
alert("Success");
}
else
{
alert("Some trouble!");
}
});
The only thing that I see missing in your code is the name property of your dropdown.
<select id="ddlSelect" name="ddlSelect" class="form-control">
#foreach (var item in Model.Persons)
{
<option value="#item.Id">#item.Name</option>
}
</select>
for your first example your using FormCollection
string option = form["ddlSelect"].ToString();
but your DropDown doesn't have a name property and form collection is using the name property as reference that is why you are getting a null value.
same goes with your second example reference the DropDown name property instead of ID in your Parameter
public ActionResult SetOptionForUser(int myDropDownName) //null
{
string option = myDropDownName.ToString(); //null error
return RedirectToAction("AnotherAction", "AnotherController");
}
The FormCollection in ASP.NET MVC is tied to the name attribute of input elements, add the name attribute to your select HTML element, like this:
<select id="ddlSelect" name="ddlSelect" class="form-control">
Note: The id attribute is how to find things in the DOM and the name attribute is for what gets included/submitted in the form
As for the JavaScript jQuery AJAX POST issue, I believe the issue is that jQuery is making an intelligent guess that your optionId is text. You should create an object literal to hold the JSON data and then stringify that value to send to the controller, like this:
var dataForServer = {
optionId: optionId
};
$.post(#Url.Action("SetOptionForUser", "MyController"),
JSON.stringify(optionId),
null,
json);
The FormCollection in ASP.NET MVC is getting to the name attribute of input elements
so add this attribute name="ddlSelect"
MattoMK,
Please post code for your Model.
Typically, a model will hold all the data required for your webform to run and your post to send the data back. In your view, you should be selecting to a Model field. You seem to have Model.Persons, which is likely an enumerable of a class describing people.
MODEL
You did not describe your model, so a fake one is shown with just two properties, a string to hold the list selection and your list of Persons. Hopefully, your HttpGet Action populates your model correctly.
public class MyModel
{
public string ddSelect { get ; set; }
public List<Person> Persons { get ; set; }
}
HTML (often called the View)
We explicitly tell the world that this view uses this Model.
#model MyModel // Tell MVC what model we are using for this view
#using (Html.BeginForm("SetOptionForUser", "MyController", FormMethod.Post, new { #class="form-inline" }))
{
#Html.AntiForgeryToken()
<div class="text-center">
<div class="form-group">
#Html.DropDownListFor(m => m.ddSelect, Model.PersonList, new {id = "ddlSelect"})
</div>
<button type="submit" class="btn btn-primary" id="btnEnter">Go</button>
</div>
}
MVC Controller
Your controller is expecting your view to return a model of type MyModel and thus will try to push the form variables into a copy of your model (if it can). Since your form does not fill out a model property, you get nulls back.
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult SetOptionForUser(MyModel theModel, FormsCollection collection)
{
var selectedName = theModel.ddSelect;
return RedirectToAction("AnotherAction", "AnotherController");
}
This should return the value you selected from the dropdown list. Pay attention to the generated HTML from your site (Press F12 in browser and view source) to see how MVC does things. It's easier to play along than to fight it. In the above POST Action, see the included parameter collection... That holds all of the form variables. It can be gone through to find non model values if required. It is not necessary and can be removed, but poking around in that collection affords a nice view of how data is structured upon POST.
Hope this Helps.

DropDown not displaying what was previously selected & saved

The customer can view their cust details page where they can change their pre-recorded delivery run (if they wish too) I have a drop down list containing towns for delivery runs:
<div class="editor-label">#Html.DropDownListFor(model => model.DeliveryRunList, Model.DeliveryRunList)</div>
When the customer profile loads it displays the correct town in the drop down(reading from the DB, which they previously selected when registering).
However if they change the town and save it, the user is returned to the home page and the newly selected tow is saved to the DB. But, if the user returns to the customer profile page the drop down displays the previously selected town, as opposed to the new one just previously selected and saved to the DB. Is it being stored in the cache somewhere.
Why is it not updating to what is actually in the DB??
Codebehind:
CustomerPart custPart = _custService.Get(custId);
if (DeliveryRunList.HasValue)
{
custPart.DeliveryRun_Id = DeliveryRunList.Value;
}
_custService.Update(custPart);
Thanks
I suppose model is a CustomerPart instance, and you have defined it more or less in this way.
public class CustomerPart
{
public int DeliveryRun_Id {get; set;}
public SelectList(or some IEnumerable) DeliveryRun_Id
}
I feel your code isn't updating the DB since you use the wrong attributes. The first lambda expression should be model => model.TheAttributeYouWantToUpdate, in this case DeliveryRun_Id.
So it should be:
#Html.DropDownListFor(model => model.DeliveryRun_Id, Model.DeliveryRunList)
rather than
#Html.DropDownListFor(model => model.DeliveryRunList, Model.DeliveryRunList)
It's not even clear where is this code inside the controller:
CustomerPart custPart = _custService.Get(custId);
if (DeliveryRunList.HasValue)
{
custPart.DeliveryRun_Id = DeliveryRunList.Value;
}
_custService.Update(custPart);
A common way of doing it is to have two methods of the same name for editing, one for HttpGet and one for HttpPost, and use a #Html.BeginForm() in the razor view for updating, rather than updating the info in controller.
Example:
public ActionResult Edit(int id = 0) {
InvestmentFund Fund = InvestmentFundData.GetFund(id);
return Fund == null ? (ActionResult)HttpNotFound() : View(Fund);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(InvestmentFund Fund)
{
if (ModelState.IsValid)
{
InvestmentFundData.Update(Fund);
return RedirectToAction("List");
}
return View(Fund);
}
In View
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#* For the attributes of your model *#
#Html.LabelFor ...
#Html.EditorFor ...
#Html.ValidationMessageFor ...
<input type="Submit"m value="Save">
}

MVC 3 Razor DropdownListFor - How to "filter" the view after value is selected

So I took some advice to create a DropDownListFor element in my view, which meant to create a model view called
MODEL
class StudentModelView.
I have two properties.
StudentID{get;set;}
IEnumerable<SelectListItem> SelectPeopleList { get;set;}
I get the list to populate nicely with this code
VIEW
#Html.DropDownListFor(x => x.StudentID, Model.SelectPeopleList,"--Select Students--", new Dictionary<string,object>{ {"class","dropdowns"},{"id","selectPeopleDDL"}})
//NEED A BUTTON TO SUBMIT
CONTROLLER
public ActionResult Index()
{
return View(new StudentModelView());
}
What kind of button do I need to make it post
After posting, how do I update my view to show the new filtered list? Am I missing a POST controller or just ajax? What's the best approach?
You could do it all using jquery, but here is couple of pointers:
You should wrap your filter in a form:
#using (Html.BeginForm("Home", "Index", FormMethod.Get))
{
#Html.DropDownListFor(x => x.StudentID, Model.SelectPeopleList,"--Select Students--", new Dictionary<string,object>{ {"class","dropdowns"},{"id","selectPeopleDDL"}})
<input type="submit" value="Go" />
}
the submit button is not a must, you could just use jquery to submit whenever the value of the dropdown changes
in your controller:
public ActionMethod Index(int? studentID)
{
var model = new StudentModelView
{
StudentId = studentID,
SelectPeopleList=GetListFiltered(studentId)
}
return(model);
}

Categories

Resources