How to authorise user from the forum's main page? - asp.net-mvc-3

I'm trying to implement a simple blog, which contains topics
models/Topic.cs
public class Topic
{
public int ID {get; set;}
[StringLength(50)]
[RequiredAttribute(ErrorMessage = "*")]
public string Title {get; set;}
[StringLength(1024)]
[RequiredAttribute(ErrorMessage = "*")]
public string Body { get; set; }
public int CommentsCount { get; set; }
public DateTime TimeLastUpdated { get; set; }
public int AuthorID { get; set; }
public virtual List<Comment> commentsList { get; set; }
}
Main Page looks like a list of topics.
Controllers/HomeController.cs
public class HomeController : Controller
private ContentStorage db = new ContentStorage();
public ViewResult Index()
{
// Topics = DbSet<Topic> Topics { get; set; }
return View(db.Topics.ToList());
}
[HttpPost]
public void LogIn(string login, string password)
{
int i;
i = 10;
}
}
Main page's view is very simple.
Views/Home/Index
#model IEnumerable<MvcSimpleBlog.Models.Topic>
...
<table width="95%" height="86" border="0">
<tr>
<td width="45%" valign = "bottom" >Login:</td>
<td width="45%" valign = "bottom" >Password:</td>
<td width="10%"></td>
</tr>
<tr>
<td width="45%"><p> <input type="text" name="login" /> </p></td>
<td width="45%"><p><input type="password" name="password" /></p></td>
<td width="10%" align = "left">
#using (Html.BeginForm("LogIn", "Home"))
{
<input type = "submit" value = "Enter" />
}
</td>
</tr>
<tr>
<td width="45%" valign = "top" >#Html.ActionLink("Register", "Register", "Account")</td>
</tr>
</table>
How could i pass the values from edit boxes in the View to the HomeController method? The method "LogIn" was supposed to receive data from the view, call the "Account" controller, passing user's login and password to it. An "Account" controller shoud validate this user and redirect browser to the main page with topics.
But i can't access login and password edit boxes in the view... and i really don't know what should i do, and is my model correct

Those input fields should be inside your Html.BeginForm if you want their values to be posted to the server when the form is submitted. Currently you only have a single submit button inside your form. So:
#using (Html.BeginForm("LogIn", "Home"))
{
<table width="95%" height="86" border="0">
<tr>
<td width="45%" valign="bottom">Login:</td>
<td width="45%" valign="bottom">Password:</td>
<td width="10%"></td>
</tr>
<tr>
<td width="45%">
<p>
<input type="text" name="login" />
</p>
</td>
<td width="45%">
<p>
<input type="password" name="password" />
</p>
</td>
<td width="10%" align="left">
<input type="submit" value="Enter" />
</td>
</tr>
<tr>
<td width="45%" valign="top">
#Html.ActionLink("Register", "Register", "Account")
</td>
</tr>
</table>
}
Now your LogIn controller action could receive the 2 values as action parameters like so:
[HttpPost]
public ActionResult LogIn(string login, string password)
{
... perform authentication
}

Related

ASP.NET Core 3.1 MVC : sending selected checkboxes to controller

I have following list view with checkboxes:
#model IEnumerable<PaketServisAracTakip.Models.Item>
#{
ViewData["Title"] = "Yükleme Yap";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2 class="text-center text-success">#ViewBag.name İsimli Araca Yükleme Yap</h2>
<form asp-controller="Vehicle"
asp-action="LoadItem" method="post">
<br />
<input type="submit" name="submit" value="Oluştur" class="btn btn-primary" />
</form>
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th class="text-center">
Yüklensin mi?
</th>
<th class="text-center">
#Html.DisplayNameFor(model => model.Name)
</th>
<th class="text-center">
#Html.DisplayNameFor(model => model.Price)
</th>
<th class="text-center">
#Html.DisplayNameFor(model => model.Description)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
<div class="form-check">
<label class="form-check-label" for="#item.Id" asp-validation-for="#item.Id"></label>
<input class="form-check-input" name="ids" type="checkbox" value="#item.Id" id="#item.Id">
</div>
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
₺#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
</tr>
}
</tbody>
</table>
And my item model with database integrated:
[Table("Items")]
public class Item
{
[Key]
public int Id { get; set; }
[Display(Name = "İsim")]
[Required(ErrorMessage ="{0} alanı boş bırakılamaz.")]
[MaxLength(50, ErrorMessage ="İsim 50 karakteri geçemez.")]
public String Name { get; set; }
[Display(Name = "Fiyat")]
[Required(ErrorMessage = "{0} alanı boş bırakılamaz.")]
[Range(0, Double.MaxValue, ErrorMessage = "Minimum 0 girmelisin.")]
public int Price { get; set; }
[Display(Name = "Açıklama")]
public String Description { get; set; }
}
view
So when button is clicked i want to get checked items in my controller. I tried this but its empty:
[HttpPost]
public ActionResult LoadItem(IEnumerable<Item> model)
{
return RedirectToAction("Index");
}
I also tried int array and FormCollection but didn't work. I think I need some tag helpers but don't know which.
when button is clicked i want to get checked items in my controller. I
tried this but its empty
Please check the code in the View Page, since the table doesn't in the <form> element, when you click the Submit button, the submitted form doesn't contain the related data.
Besides, to submit the model data to the controller using model binding, we should use the #for statement to loop through the entities and use hidden fields to store the related data. Please refer the following sample and change your code:
Model:
[Table("Items")]
public class Item
{
[Key]
public int Id { get; set; }
[Display(Name = "İsim")]
[Required(ErrorMessage = "{0} alanı boş bırakılamaz.")]
[MaxLength(50, ErrorMessage = "İsim 50 karakteri geçemez.")]
public String Name { get; set; }
[Display(Name = "Fiyat")]
[Required(ErrorMessage = "{0} alanı boş bırakılamaz.")]
[Range(0, Double.MaxValue, ErrorMessage = "Minimum 0 girmelisin.")]
public int Price { get; set; }
[Display(Name = "Açıklama")]
public String Description { get; set; }
public Boolean IsChecked { get; set; } //add a property to store whether the item is check or not.
}
View page:
#model List<netcore3_1sample.Models.Item>
#{
ViewData["Title"] = "ItemIndex";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2 class="text-center text-success">#ViewBag.name İsimli Araca Yükleme Yap</h2>
<form asp-controller="Home"
asp-action="LoadItem" method="post">
<br />
<input type="submit" name="submit" value="Oluştur" class="btn btn-primary" />
<br />
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th class="text-center">
Yüklensin mi?
</th>
<th class="text-center">
Name
</th>
<th class="text-center">
Price
</th>
<th class="text-center">
Description
</th>
</tr>
</thead>
<tbody>
#for( var i = 0; i < Model.Count;i++)
{
<tr>
<td>
<div class="form-check">
<label class="form-check-label" for="#Model[i].Id" asp-validation-for="#Model[i].Id"></label>
<input class="form-check-input" name="ids" type="checkbox" value="#Model[i].Id" id="#Model[i].Id">
#*<input type="checkbox" asp-for="#Model[i].IsChecked" />*#
<input type="hidden" asp-for="#Model[i].Id" />
</div>
</td>
<td>
#Html.DisplayFor(modelItem => Model[i].Name)
<input type="hidden" asp-for="#Model[i].Name" />
</td>
<td>
₺#Html.DisplayFor(modelItem => Model[i].Price)
<input type="hidden" asp-for="#Model[i].Price" />
</td>
<td>
#Html.DisplayFor(modelItem => Model[i].Description)
<input type="hidden" asp-for="#Model[i].Description" />
</td>
</tr>
}
</tbody>
</table>
</form>
Code in the controller:
[HttpPost]
public ActionResult LoadItem(List<Item> model, int[] ids)
{
return RedirectToAction("ItemIndex");
}
According to your code, you are using a html checkbox element to store the selected Item ID, so here we need to add an array to get the selected ids.
Besides, you could add a IsChecked property in the Item model, then change the following code:
<input class="form-check-input" name="ids" type="checkbox" value="#Model[i].Id" id="#Model[i].Id">
to
<input type="checkbox" asp-for="#Model[i].IsChecked" />
By using this method, in the controller, you could filter the selected item based on the IsChecked property.
The result like this:

How To Send List Of Data From View To Controller With Ajax Form in Mvc4

How To Send List Of Data From View To Controller With Ajax Form In Mvc4 :
My Model Sample :
public class Food
{
public string name { get; set; }
public int quantity { get; set; }
}
public class CustomerModel {
public string CustomerName { get; set; }
public List<Food> ListFoods { get; set; }
}
[HttpPost]
public ActionResult AddCustomer(CustomerModel model)
{
//Add New Person
return Json(new { Result = "OK" });
}
My View :
#using (Ajax.BeginForm("AddCustomer", "Resturant", new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "Success"
}, new { #id = "frmaddCustomer" }))
{
<p>
<label>Customer Name </label>
</p>
<p>
#Html.CH_TextBox("CustomerName").size(TextBoxSize.Medium)
</p>
<p>
Food List
</p>
<table id="FoodList" class="static-table" data-bind='visible: gifts().length > 0'>
<thead>
<tr>
<td style="width: 250px;">Name</td>
<td>Quantity</td>
<td />
</tr>
</thead>
<tbody data-bind='foreach: gifts'>
<tr>
<td>
#Html.CH_TextBox("Food.name").size(TextBoxSize.Medium)
</td>
<td>
#Html.CH_TextBox("Food.quantity").size(TextBoxSize.Medium)
<td>
<a id="deleteRow">Delete</a>
</tr>
</tbody>
</table>
<button data-bind='click: addGift' type="submit">New Food</button>
<button data-bind='enable: gifts().length > 0' type="submit">Send Data</button>
}
I use the following method to post data to controller model :
<tr>
<td>
#Html.CH_TextBox("Food[0].name").size(TextBoxSize.Medium)
</td>
<td>
#Html.CH_TextBox("Food[0].quantity").size(TextBoxSize.Medium)
</td>
<td>
<a id="deleteRow">Delete</a>
</td>
</tr>
<tr>
<td>
#Html.CH_TextBox("Food[1].name").size(TextBoxSize.Medium)
</td>
<td>
#Html.CH_TextBox("Food[1].quantity").size(TextBoxSize.Medium)
</td>
<td>
<a id="deleteRow">Delete</a>
</td>
</tr>
<tr>
<td>
#Html.CH_TextBox("Food[2].name").size(TextBoxSize.Medium)
</td>
<td>
#Html.CH_TextBox("Food[2].quantity").size(TextBoxSize.Medium)
</td>
<td>
<a id="deleteRow">Delete</a>
</td>
</tr>
by using this method, my problem was solved.
Thanks .

Value is not getting pass from view to action method

i am new in mvc. i have design a form and when i am click the submit button then right action method is calling but form field's value are not getting pass.
here is my view code
<div id="mydiv">
#using (Html.BeginForm("Save", "Game", FormMethod.Post, new { #Id = "Form1" }))
{
<table border="0">
<tr>
<td>Name :</td>
<td><input name="name" type="text" /></td>
</tr>
<tr>
<td>Salary :</td>
<td><input name="salary" type="text" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Save" /> </td>
</tr>
</table>
}
</div>
here is my action method
public ActionResult Save(string str1, string str2)
{
return View("Message");
}
when save is getting called the str1 & str2 is being null please help me to pass value and also discuss various trick to pass value from view to action method. thanks
Change you controller
public ActionResult Save(string name, string salary)
{
return View("Message");
}
As you have to use variable name which you have defined in input
<input name="name" type="text" />
<input name="salary" type="text" />
If you want to return partial view.
return PartialView("Message", <<OptionalPartialViewModel>>);
You should start by learning about conventions in ASP.NET MVC. You should use models for communicating between controllers and views.
Create a model type first:
public class SalaryModel
{
public string Name { get; set; }
public string Salary { get; set; }
}
Create your form by using HTML helpers and strongly typing your view:
#model SalaryModel
<div id="mydiv">
#using (Html.BeginForm("Save", "Game", FormMethod.Post, new { #Id = "Form1" }))
{
<table border="0">
<tr>
<td>Name :</td>
<td>#Html.TextBoxFor(item => item.Name)</td>
</tr>
<tr>
<td>Salary :</td>
<td><input name="salary" type="text" /></td>
</tr>
<tr>
<td colspan="2">#Html.TextBoxFor(item => item.Salary)</td>
</tr>
</table>
}
</div>
Then you can get the form values inside the model:
[HttpPost]
public ActionResult Save(SalaryModel model)
{
return View("Message");
}
There's a great tutorial on ASP.NET MVC website that can help you with the basics.
MVC Bind form inputs to Action by their names. You should change your method params as the same of the form. Also, you are missing the HttpPost attribute:
[HttpPost]
public ActionResult Save(string name, string salary)
{
/*Do Stuff here*/
return View("Message");
}

MVC3 IPagedList in ViewModel

I want to have a page that has a form on the top of the page to enter movies in a system, and on the bottom of the page I want to have a table to display all of the movies in inventory. I am getting an error saying: Value cannot be less than 1. Parameter name: Page Size.
I have a viewmodel that currently looks like this:
public class InventoryViewModel
{
public Inventory Inventory { get; set; }
public IPagedList<Inventory> InventoryList { get; set; }
}
In my controller I have:
public ActionResult Index(int? page)
{
ViewBag.MoviesList = new SelectList(inventoryRepository.Movies, "MovieId", "Title");
InventoryViewModel vm = new InventoryViewModel
{
Inventory = new Inventory(),
InventoryList = inventoryRepository.GetInventory.ToPagedList(page.HasValue ? page.Value - 1 : 0, defaultPageSize)
};
return View(vm);
}
In my view I have:
<div class="well">
<h4>Enter Movie in System:</h4>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true, "Movie was not entered in system. Please correct the errors and try again.")
<div>
<div class="input-prepend">
<span class="add-on"><i class="icon-film"></i></span>
#Html.DropDownListFor(m => m.Inventory.MoviesId, (SelectList)ViewBag.MoviesList)
#Html.ValidationMessageFor(m => m.Inventory)
</div>
<div class="input-prepend">
<span class="add-on"><i class="icon-calendar"></i></span>
#Html.TextBox("Quantity")
</div>
<p><button class="btn btn-primary" type="submit" value="Submit">Submit</button></p>
#Html.ValidationSummary()
</div>
}
</div>
<div>
<h3>Current Inventory:</h3>
</div>
<table class="table table-bordered table-hover">
<thead>
<tr>
<th style="width: 15%;">Checkout Number</th>
<th style="width: 15%;">Title</th>
<th style="width: 23%;">Availability</th>
<th style="width: 17%;"></th>
</tr>
</thead>
<tbody>
#foreach (var vm in Model.InventoryList.OrderBy(m => m.CheckoutNum))
{
<tr>
<td>#vm.CheckoutNum</td>
<td>#vm.Movies.Title</td>
<td>#vm.isAvail</td>
<td>
</td>
</tr>
}
</tbody>
<tfoot>
<tr>
<td colspan="4">
#Html.Pager(Model.InventoryList.PageSize, Model.InventoryList.PageNumber, Model.InventoryList.TotalItemCount).Options(o => o
.DisplayTemplate("BootstrapPagination").RouteValues(new { q = ViewBag.Query, area = "" } )
.AlwaysAddFirstPageNumber().MaxNrOfPages(5))
</td>
</tr>
</tfoot>
</table>
I figured it out. I was setting the defaultPageSize in the wrong constructor, so the variable was never getting set, causing the page size to be 0.
int defaultPageSize;
private IInventoryRepository inventoryRepository;
public InventoryController()
{
this.inventoryRepository = new InventoryRepository(new MovieContext());
this.defaultPageSize = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["defaultPageSize"]);
}
public InventoryController(IInventoryRepository inventoryRepository)
{
this.inventoryRepository = inventoryRepository;
this.defaultPageSize = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["defaultPageSize"]);
}

How to do a bulk persist on a partial view?

I have written a partial view that displays a list of rows, where some fields in the row are editable using a textbox, checkbox, or whatever.
I would like the parent view to have a "submit" button that posts the whole collection of updated rows so that I can do a group update rather than posting once for every updated row.
Here's what I have:
public class GroupModel {
public string SomeGenericProperty { get; set; }
public IEnumerable<ItemModel> Items { get; set; }
}
public class ItemModel {
public long ID { get; set; }
public string Field1 { get; set; }
public string Field2 { get; set; }
}
Then I have a view "GroupDetails":
#model MyNamespace.GroupModel
...
#using (Html.BeginForm("SaveItems", "Home")) {
<fieldset>
...
#Html.Partial("ItemList", Model.Items)
...
<input type="submit" value="Approve" />
</fieldset>
}
And a partial view "ItemList":
#model IEnumerable<MyNamespace.ItemModel>
<table>
<tr>
<th>
Field 1
</th>
<th>
Field 2
</th>
<th>
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.TextBoxFor(modelItem => item.Field1)
</td>
<td>
#Html.TextBoxFor(modelItem => item.Field2)
</td>
<td>
#Html.HiddenFor(i => item.ID)
</td>
</tr>
}
</table>
But when I post, the information from partial view is not being posted; the GroupModel object's Items property is null.
What's the right way to do this?
I would recommend you to always use editor templates. The reason your code doesn't work is because you used a partial and this partial doesn't inherit the parent template context which means that helpers that are used inside it will generate wrong names for the input fields.
For example if you look at the source code of your page you will see this:
<td>
<input type="text" name="[0].Field1" id="[0]_Field1" />
</td>
instead of the correct name which is:
<td>
<input type="text" name="Items[0].Field1" id="Items[0]_Field1" />
</td>
I would recommend you reading the following blog post to better understand the wire format that the default model binder expects.
So start by fixing your main view first and replace the partial with an editor template:
#model MyNamespace.GroupModel
#using (Html.BeginForm("SaveItems", "Home"))
{
<fieldset>
...
<table>
<thead>
<tr>
<th> Field 1 </th>
<th> Field 2 </th>
<th></th>
</tr>
</thead>
<tbody>
#Html.EditorFor(x => x.Items)
</tbody>
</table>
...
<input type="submit" value="Approve" />
</fieldset>
}
and then define a custom editor template that will be rendered for each element of the model (~/Views/Shared/EditorTemplates/ItemModel.cshtml - this works by convention, it should be either inside ~/Views/Shared/EditorTemplates if you want it to be reused among controllers or inside ~/Views/Home/EditorTemplates if you want this template to be available only for the Home controller - and the name of the template must be the type of the collection - in your case it is ItemModel.cshtml):
#model MyNamespace.ItemModel
<tr>
<td>
#Html.TextBoxFor(x => x.Field1)
</td>
<td>
#Html.TextBoxFor(x => x.Field2)
</td>
<td>
#Html.HiddenFor(x => x.ID)
</td>
</tr>
Now everything will bind fine and dandy in your controller action:
[HttpPost]
public ActionResult SaveItems(GroupModel model)
{
...
}

Resources