I have a list of categories that I want to edit. I can successfully pass them into the controller.
public ActionResult Edit()
{
if (!IsAdmin) return RedirectToAction("Index", "Home");
ViewBag.IsAdmin = IsAdmin;
var categories = _model.Categories.ToList();
return View(categories);
}
Then I have a view to edit the names of the categories.
#using MyStructures.Models
#model List<MyStructures.Models.Category>
#using (Html.BeginForm("Update", "Categories", FormMethod.Post))
{
foreach (var category in Model)
{
var categoryToEdit = #category;
<table>
<tr>
<td>Category Number: #category.Id</td>
<td>#Html.EditorFor(x => categoryToEdit.Name)</td>
<td colspan="2">
<input type="submit" value="Save"
formaction=#Href("~/Categories/Update/") />
</td>
</tr>
</table>
}
<input type="submit" value="Cancel"
formaction=#Href("~/Home/Index/") />
}
How do I pass the updated value to the "Update" controller? The value of Category obj is null.
[HttpPost]
public ActionResult Update(Category obj)
{
var existing = _model.Categories.Find(obj.Id);
existing.Name = obj.Name;
_model.SaveChanges();
return RedirectToAction("Index", "Home");
}
Related
I am new to MVC and I am trying populate a list of item in the MVC view class, but the model object is null in the .cshtml file during the startup.
#foreach (var element in Model)
Thanks for your help.
My Code:
public class HomeController : Controller
{
List<ModelMath> mathList = new List<ModelMath>();
[HttpPost]
public ActionResult Submit(FormCollection fc)
{
mathList = new List<ModelMath>();
int num = Convert.ToInt32(fc["Num"]);
while(num > 1)
{
ModelMath modelMath = new ModelMath();
modelMath.Number = num;
mathList.Add(modelMath);
num--;
}
return View(mathList);
}
}
Model class:
public class ModelMath
{
public int Number { get; set; }
}
Index.cshtml
#{
ViewBag.Title = "Home Page";
}
<h3><b>HTTPPost Method</b></h3>
#using (Html.BeginForm("Submit", "Index", FormMethod.Post))
{
<table>
<tr>
<td>Enter a Number: </td>
<td>#Html.TextBox("Num")</td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Submit"></td>
</tr>
</table>
}
<h4 style="color:purple">
<div class="panel-body">
<div class="col-md-12" style="margin-top: 15px;">
<table class="table table-bordered table-responsive table-hover">
<tr>
<th>Input Numbers </th>
</tr>
#foreach (var element in Model)
{
<td>#d.Number</td>
}
</table>
</div>
</div>
</h4>
Could you please let me know what's wrong with my code? Thanks again for your help.
In your Index function, you need to populate the model and pass to the view. Something like
Public ActionResult Index()
{
var myList = new List<example>();
return view(myList)
}
and in your view:
#model List<example>
That is what populates your index view model. It would help if you show us the controller function returning your index view.
you should write the type of Model at first of your View
#model List<ModelMath>
and for showing a view you need [HttpGet] attribute action
[HttpGet]
Public ActionResult Index()
{
//var mathList= new list<ModelMath>();
return view(mathList)
}
when I run my code it seems that my HttpGet method works fine. But when I try to return the value to my HttpPost action it just runs my HttpGet method and then I get an "NullReferenceException" error.
Here is my code.
My Actions in my controller:
[HttpGet]
public IActionResult AddMovie(int? id)
{
List<Movie> movieList = new List<Movie>();
movieList = dbContext.Movies.ToList();
AddMovieViewModel viewModel = new AddMovieViewModel()
{
movies = movieList,
customer = dbContext.Customers.Where(s => s.CustomerId == id).FirstOrDefault()
};
return View(viewModel);
}
[HttpPost]
public IActionResult AddMovie (int id,int cid)
{
Customer customer = dbContext.Customers.Where(s => s.CustomerId == cid).FirstOrDefault();
Movie movie = dbContext.Movies.Where(s => s.MovieId == id).FirstOrDefault();
customer.BorrowingMovies.Add(movie);
customer.BorrowingMovies.Add(movie);
return View();
}
And here my view
#model MovieExampleAppDotNetCore.ViewModels.AddMovieViewModel
#{
ViewData["Title"] = "AddMovie";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>AddMovie</h1>
<label>Add movie for: #Model.customer.Name</label>
<table style="width:100%" class="table table-bordered table-hover">
<tr>
<th>Name</th>
</tr>
#foreach (var movie in Model.movies)
{
<tr>
<td>#movie.Name</td>
<td>
#Html.ActionLink("Select", "AddMovie", new { id = movie.MovieId, cid = Model.customer.CustomerId })
</td>
</tr>
}
</table>
I hope someone can help me with my problem.
The HTML ActionLink does not work with POST so is hitting your GET method. See this question.
To overcome and resolve your issue, wrap the button in a Form, something like this should do the trick.
#using (Html.BeginForm("AddMovie", "ControllerName", new { id = movie.MovieId, cid = Model.customer.CustomerId }, FormMethod.Post))
{
<button class="btn btn-primary" type="submit">
Add Movie
</button>
}
I'm new with asp.net MVC and studying with some example code.
I'm referrence the sample from https://github.com/LaunchCodeEducation/cheese-mvc.
And I want to add new action and view for the example. Such as add a delete link/button to delete a cheese from cheese/index page directly:
But it seems there have something wrong with the SingleRemove action and view I wrote.
The action I use as below:
[HttpGet]
public IActionResult SingleRemove()
{
ViewBag.cheeses = context.Cheeses.ToList();
return View();
}
[HttpPost]
public IActionResult SingleRemove(int cheeseId)
{
Cheese theCheese = context.Cheeses.Single(c => c.ID == cheeseId);
//context.Cheeses.Remove(theCheese);
//context.SaveChanges();
return View(theCheese);
}
And the view I use as :
#model CheeseMVC.Models.Cheese
<h1>Going to be removed cheese information as below</h1>
<form >
<ul>
<li>Cheese ID: #Model.ID</li>
<li>Cheese Name: #Model.Name</li>
<li>Cheese Type: #Model.Type</li>
<li>Cheese Description: #Model.Description</li>
</ul>
<input type="submit" value="Remove Selected Cheese" />
</form>
Could you please guide how to set the action and model correctly?
And how to let a pop-up window to double confirm the deletion on a cheese?
If you create a Controller and select "Controller with views, using Entity Framework" it will create all of that for you based on your model. You could then go back and make it pretty with ccs to use buttons instead of links ect.. I am not sure what your view is doing in the above code. Your view should be
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Description</th>
<th></th>
</tr>
</thead>
foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.Name)</td>
<td>#Html.DisplayFor(modelItem => item.Type)</td>
<td>#Html.DisplayFor(modelItem => item.Description)</td>
<td>
#using (Html.BeginForm("Delete", "controller name goes here", FormMethod.Post))
{
#Html.AntiForgeryToken()
<input type="hidden" id="id" value="#item.ID" />
<input onclick="return confirm('Are you sure you want to delete the Cheese?');" type="submit" value="Delete" class="btn btn-primary " />
}
</td>
</tr>
}
</table>
Then in your Controller you would have something like this:
public ActionResult Delete(int? ID)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Cheese cheese = db.Cheese.Find(id);
if (cheese == null)
{
return HttpNotFound();
}
return View(Index);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult Delete(int ID)
{
var cheese = db.cheese.Find(id);
if (cheese != null)
{
Cheese cheese = db.Cheese.Find(id);
db.Cheese.Remove(cheese);
db.SaveChanges();
return RedirectToAction("Index");
}
return RedirectToAction("Index", "Cheese");
}
Make sure your are using:
using System.Data.Entity;
using System.Linq;
using System.Net;
And also not sure what your context is but this is where the db.Cheese comes from:
private ApplicationDbContext db = new ApplicationDbContext();
i want in my page after an action like RegisterUser give a message to client for result.so i use TempData(becase i use RedirectToAction method i cant use viewbag).my problem is that if user open another tab in same time message will show in another tab(any page it can be).how can i solve that??
#using (#Html.BeginForm("RegisterUser", "UserManagement", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.Partial("_RegisterPagesMessage")
<table class="Registertbl">
<tr>
<td>نام*</td>
<td> #Html.TextBoxFor(m => m.FName, new { maxlength = 20})<br />
</td>
<td>سمت*</td>
<td>#Html.TextBoxFor(m => m.Post, new { maxlength = 200})</td>
</tr>
</table>
<br />
<input type="submit" value="Insert" class="insertBtn" />
#Html.ActionLink("back", "ViewUserList", "UserManagement")
}
//_RegisterPagesMessage
#if (TempData["MessageResult"] == null)
{
<div id="ErrorContent" class="msg-Red" style="display: none;"></div> <br />
}
else
{
<div id="ErrorContent" class="#TempData["cssClass"]" >
#Html.Label(TempData["MessageResult"] as string)
</div> <br />
}
//Controller
[HttpGet]
public ActionResult RegisterUser()
{
return View(new User());
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RegisterUser(Common.UsersManagement.Entities.User model)
{
SetUserManagement();
var Result = userManagement.RegisterUser(model);
SetMessage(Result.Mode.ToString());
if (Result.Mode == Common.Extensions.ActionResultMode.Successfully)
{
return RedirectToAction("RegisterUser");
}
// if not Successfull
return View(model);
}
protected void SetMessage(string Mode)
{
var messageResult = XmlReader.FindMessagekey(Mode);
TempData["MessageResult"] = messageResult.MessageContent;
TempData["cssClass"] = messageResult.cssClass;
}
Easy solution. In your RegisterUser controller method check for a value in TempData and transfer it to ViewData, then have the View check the ViewData, which only survives for that one view.
[HttpGet]
public ActionResult RegisterUser()
{
if( TempData.ContainsKey( "MessageResult" )
{
ViewData["MessageResult"] = TempData["MessageResult"];
ViewData["cssClass"] = messageResult.cssClass;
}
return View(new User());
}
Now in the view use ViewData instead of TempData.
I am new to the MVC framework as well as ASP.NET so I apologize for any sloppy code.
I am creating an application that requires an Admin to set the roles of new users that register. When the Admin logs into the application, they are automatically directed to an Admin page that displays a list of users that have registered with the app. The admin has the ability to choose the role for the new user.
Here is my controller for the admin:
public class AdminTestController : Controller
{
private UsersContext db = new UsersContext();
// GET: /AdminTest/
[Authorize(Roles = "Admin")]
public ActionResult Index()
{
var model = db.UserProfiles.ToList();
return View(model);
}
[HttpPost]
public ActionResult Submit(string userName, string selectedRole)
{
Roles.AddUserToRole(userName,selectedRole);
return View("Index");
}
Here is the corresponding view:
#model IEnumerable<WAP.Models.UserProfile>
#{
ViewBag.Title = "Index";
}
...
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserId)
</td>
<td>
</td>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.UserId }) |
#Html.ActionLink("Details", "Details", new { id=item.UserId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.UserId })
#using (Html.BeginForm("Submit", "AdminTest", FormMethod.Post))
{
<select name ="selectedRole">
<option value="Null"></option>
<option value="Manager">Manager</option>
<option value="Agent">Agent</option>
</select>
<input id="SubmitChange" type="submit" value="Submit" />
<input id="userName" type ="text" value= "#item.UserName" name= "userName" hidden ="hidden" />
}
</td>
</tr>
}
Thank you in advance for taking the time to look at this question and any help that you can provide.
You can use Html.DropDownList helper for this. Firstly you will need to prepare your roles collection in controller to populate it. Here is the sample code:
[Authorize(Roles = "Admin")]
public ActionResult Index()
{
var model = db.UserProfiles.ToList();
var rolesCollection = new List<string> {"Null", "Manager", "Agent"};
ViewBag.Roles = new SelectList(rolesCollection);
return View(model);
}
Then in your view:
#using (Html.BeginForm("Submit", "AdminTest", FormMethod.Post))
{
#Html.Hidden("userName", item.UserName)
#Html.DropDownList("selectedRole", (SelectList)ViewBag.Roles)
<input id="SubmitChange" type="submit" value="Submit" />
}
You can also use Html.RadioButton helper in such way:
#using (Html.BeginForm("Submit", "AdminTest", FormMethod.Post))
{
#Html.Hidden("userName", item.UserName)
#Html.RadioButton("selectedRole", "Null", true)
#Html.RadioButton("selectedRole", "Manager")
#Html.RadioButton("selectedRole", "Agent")
<input id="SubmitChange" type="submit" value="Submit" />
}
If you want to make multiple roles selected at the same time, I suggest using some jQuery plugin, such as jQuery.chosen and Html.ListBox helper.
Use EditorTemplates for all enums (Create "Role" enum):
#model Enum
#Html.DropDownListFor(m => Enum.GetValues(Model.GetType()).Cast<Enum>().Select(m =>
new SelecteListItem {Selected = "your logic", Text = "", Value = ""}))
Or use custom partial view by current enum.