asp.net mvc pass parameters between view and controller - c#

I am a novice in asp.net and i want create simple database application.
I need pass parameters between view and controller to retrieve data from database.
i need only this data which title is "something". I create simple left menu which contains search settings.
This is my view page.
#model IEnumerable<TwojaBiblioteka.Models.Ksiazka>
#{
ViewBag.Title = "Home Page";
}
#Styles.Render("~/Content/css")
<div class="jumbotron">
<script src="~/Scripts/jquery-2.1.4.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<div class="container">
<div class="row">
<div class="col-md-2">
<h2>Szukaj</h2>
<div class="textboxes">
<input type="text" name="Tytul" class="form-control" id="Tytul" placeholder="Tytuł..." />
<input type="text" name="txtAutor" class="form-control" id="txtAutor" placeholder="Autor..." />
<input type="text" name="txtISBN" class="form-control" id="txtISBN" placeholder="ISBN..." />
</div>
<center>
#Ajax.ActionLink("Szukaj", "SzukajKsiazki", new AjaxOptions()
{
HttpMethod="GET",
UpdateTargetId= "divKsiazki",
InsertionMode= InsertionMode.Replace
})
</center>
</div>
<div id="divKsiazki"class="col-md-10 ">
</div>
</div>
</div>
</div>
This is view for display data from database:
#model IEnumerable<TwojaBiblioteka.Models.Ksiazka>
<table class="table" style="border:1px solid black;">
<tr>
<th>
#Html.DisplayNameFor(model => model.Tytul)
</th>
<th>
#Html.DisplayNameFor(model => model.Autor)
</th>
<th>
#Html.DisplayNameFor(model => model.ISBN)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Tytul)
</td>
<td>
#Html.DisplayFor(modelItem => item.Autor)
</td>
<td>
#Html.DisplayFor(modelItem => item.ISBN)
</td>
</tr>
}
</table>
And this is my controller:
public PartialViewResult SzukajKsiazki()
{
string tytul="something";
var ksiazkilist = db.Ksiazka.Where(x => x.Tytul == tytul).ToList();
return PartialView("_ListaKsiazek",wypozyczone);
}
So how i can pass data from my textboxes to controller to display only those records which contains textbox text?

Your controller action should accept a parameter. In Asp.Net MVC, it is normal for this to be the model:
public PartialViewResult SzukajKsiazki(IEnumerable<TwojaBiblioteka.Models.Ksiazka> model)
Your view should have all of the editor elements from the model enclosed in a form and you need a submit button:
#using (Html.BeginForm("SzukajKsiazki", "ControllerName", FormMethod.Post)
{
<table class="table" style="border:1px solid black;">
<tr>
<th>
#Html.DisplayNameFor(model => model.Tytul)
</th>
<th>
#Html.DisplayNameFor(model => model.Autor)
</th>
<th>
#Html.DisplayNameFor(model => model.ISBN)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Tytul)
</td>
<td>
#Html.DisplayFor(modelItem => item.Autor)
</td>
<td>
#Html.DisplayFor(modelItem => item.ISBN)
</td>
</tr>
}
</table>
<input type="submit" value="submit">
}

Related

How do I post the row id in a custom built ASP.NET Core Razor Pages editable Grid?

I have tried several approaches, and as I'm new to Razor Pages in ASP.NET Core I'm blocked. Could anybody help me please? It must be something trivial but I googled quite a lot and I can't find a suitable way. I don't want to use jquery or any other javascript library.
Here is the relevant code:
<form method="post">
<table>
<thead>
<tr>
<th>
Text 1
</th>
<th>
Text 2
</th>
<th>
Text 3
</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model.GridRows)
{
<tr>
<td>
<input type="hidden" asp-for="#item.Id" />
</td>
<td>
#Html.EditorFor(modelItem => item.Text1)
</td>
<td>
#Html.EditorFor(modelItem => item.Text2)
</td>
<td>
#Html.EditorFor(modelItem => item.Text3)
</td>
<td>
<input type="submit" value="Save" class="btn btn-primary"/>
</td>
</tr>
}
</tbody>
</table>
</form>
public async Task<IActionResult> OnPostAsync(int id)
{
if (!ModelState.IsValid)
{
return Page();
}
var gridRowUpdate = await _context.GridRows.FindAsync(id);
if (gridRowUpdate == null)
{
return NotFound();
}
if(await TryUpdateModelAsync<GridRow>(gridRowUpdate, "GridRow", g => g.Text1, g => g.Text2, g => g.Text3))
{
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
IF you want to click each save button to send the Id of that row, You can just follow below simple demo without any jquery or any other javascript library.
<table>
<thead>
<tr>
<th>
Text 1
</th>
<th>
Text 2
</th>
<th>
Text 3
</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model.test)
{
<form method="post" >
<tr>
<td>
<input type="hidden" name="Id" value="#item.Id" />
</td>
<td>
#Html.EditorFor(modelItem => item.Text1)
</td>
<td>
#Html.EditorFor(modelItem => item.Text2)
</td>
<td>
#Html.EditorFor(modelItem => item.Text3)
</td>
<td>
<input type="submit" value="Save" class="btn btn-primary"/>
</td>
</tr>
</form>
}
</tbody>
</table>

How can I have a table with cells as inputs to update data in NET 5 MVC

I have a View with a table with this structure:
<form asp-action="Index">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<table class="table table-hover table-responsive-sm display">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Descripcion)
</th>
<th>
#Html.DisplayNameFor(model => model.Activa)
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
<input value="#Html.DisplayFor(modelitem => item.AreaClave)"/>
</td>
<td>
<input id="desc" name="desc" value="#Html.DisplayFor(modelItem => item.Descripcion)" />
</td>
<td>
<input value="#Html.DisplayFor(modelItem => item.Activa)" />
</td>
<td>
<div class="form-group">
<button asp-route-id="#item.AreaClave" type="submit" name="action">Update</button>
</div>
</td>
</tr>
}
</tbody>
</table>
I want to have multiple rows with an open input for "item.Descripcion", this is because I want to be able to update every row individually by its row ID.
This approach works just as fine for the first row, but for the following it doesn't work. I think this is because the name tag is repeated and its only considering the first one.
Is there a way to make my table with an update input in each row?
You can try to generate <form> and <table> for each item like below:
#model IEnumerable<Test>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<table class="table table-hover table-responsive-sm display">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Descripcion)
</th>
<th>
#Html.DisplayNameFor(model => model.Activa)
</th>
<th></th>
</tr>
</thead>
</table>
#foreach (var item in Model)
{
<form asp-action="Index">
<table class="table table-hover table-responsive-sm display">
<tbody>
<tr>
<td>
<input value="#Html.DisplayFor(modelitem => item.AreaClave)" />
</td>
<td>
<input id="desc" name="desc" value="#Html.DisplayFor(modelItem => item.Descripcion)" />
</td>
<td>
<input value="#Html.DisplayFor(modelItem => item.Activa)" />
</td>
<td>
<div class="form-group">
<button asp-route-id="#item.AreaClave" type="submit" name="action">Update</button>
</div>
</td>
</tr>
</tbody>
</table>
</form>
}
Backend code:
[HttpPost]
public IActionResult Index(string id,string desc)
{
//do your stufff...
}

PagedList<T> does not contain a definition for the properties of my Model <T>

I have this partial View as below:
#model IPagedList<Student>
<h2>List of Students</h2>
<div id="studentList">
<div class="pagedList" data-uwa-target="#studentList">
#Html.PagedListPager(Model,page=>Url.Action("Index",new { page }),
PagedListRenderOptions.MinimalWithItemCountText)
</div>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.LastName) //here error
</th>
<th>
#Html.DisplayNameFor(model => model.FirstName) //here error
</th>
<th>
#Html.DisplayNameFor(model => model.City) //here error
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.City)
</td>
</tr>
}
</table>
<div class="row">
<div class="col-sm-6" id="slid">
<button id="export" class="btn btn-default btn-primary" onclick="location.href='#Url.Action("ExportInCSVFormat")';return false;">Export Student List in CSV Format</button>
</div>
<div class="col-sm-4" id="excelSlide">
<button id="excelExport" class="btn btn-default btn-success" onclick="location.href='#Url.Action("ExportStudentsInExel")';return false;">Export Student List in Excel Format</button>
</div>
</div>
My Index.cshmtl is :
#model IPagedList<Student>
#{
ViewBag.Title = "Index";
}
#Html.Partial("_Student", Model)
My StudentController is
public ActionResult Index(int page=1)
{
var model = dbAllStudents.Students
.OrderByDescending(p => p.LastName)
.ToPagedList(page, 10);
return View(model);
}
The problem happens to "#Html.DisplayNameFor(model => model.LastName)". It is saying that " IPaged does not contatin a definition for LastName.
I have an idea that the problem is caused because to the Index method of Student Controller I need to add .Select but I am not sure for that. I would really appreciate if someone can help me
It's not working, because overloaded method which you want to use doesn't fit with your interface. It's for IEnumerable<> types. You can access to the first element in the list and it should returns you correct value even if list is empty.
Change your table definition to:
<table class="table">
<tr>
<th>
#Html.DisplayNameFor( => Model[0].LastName)
</th>
<th>
#Html.DisplayNameFor(_ => Model[0].FirstName)
</th>
<th>
#Html.DisplayNameFor(_ => Model[0].City)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(_ => item.LastName)
</td>
<td>
#Html.DisplayFor(_ => item.FirstName)
</td>
<td>
#Html.DisplayFor(_ => item.City)
</td>
</tr>
}
</table>
and everything will be ok.

MVC Partial View Will Not Load

I keep getting an error message along the lines of:
..but this dictionary requires a model item of type..
My view I'm trying to put the partial view into is:
#using TheNovelMachine.Models
#model TheNovelMachine.Models.Account
#{
ViewBag.Title = "Details";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<img id="homeimage" src="~/Image/front-page-book.jpg" alt="The Novel Machine" />
<div id="text" class="col-lg-12">
<h1>Profile</h1>
<div class="col-lg-6 no-gutter">
<h2>#Html.DisplayFor(model => model.Username)</h2>
<h4>#Html.DisplayFor(model => model.FullName)</h4>
<p>#Html.DisplayFor(model => model.Email)</p>
</div>
<div class="col-lg-6 pull-right text-right no-gutter">
<img class="profilepic" src="~/Image/#(Html.DisplayFor(model => model.Username)).jpg" />
</div>
<div class="col-lg-12 no-gutter">
<hr/>
<h4>#Html.DisplayFor(model => model.Username)'s Novels</h4>
#{
Html.RenderPartial("~/Views/Shared/_NovelProfile.cshtml");
}
</div>
</div>
And the Partial View is:
#using System.Web.DynamicData
#using TheNovelMachine.Models
#model IEnumerable<TheNovelMachine.Models.Novel>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
#Html.DisplayNameFor(model => model.Genre)
</th>
<th>
#Html.DisplayNameFor(model => model.Abstract)
</th>
<th>
#Html.DisplayNameFor(model => model.Privacy)
</th>
<th>
#Html.DisplayNameFor(model => model.AccountId)
</th>
</tr>
#foreach (var item in Model.Where(i => i.AccountId.ToString() == Url.RequestContext.RouteData.Values["id"].ToString())) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
#Html.DisplayFor(modelItem => item.Abstract)
</td>
<td>
#Html.DisplayFor(modelItem => item.Privacy)
</td>
<td>
#Html.DisplayFor(modelItem => item.AccountId)
</td>
</tr>
}
</table>
Your partial view is expecting this model (you are declaring it at the top of you partial view)
#model IEnumerable<TheNovelMachine.Models.Novel>
You should pass that model in this line:
#{
Html.RenderPartial("~/Views/Shared/_NovelProfile.cshtml", Model.Novels);
}
That should work, assuming Model.Novels is of this type IEnumerable<TheNovelMachine.Models.Novel> or it can be converted to that type.
Here you have an example with more details, but the idea is the same. If you don't pass this as a parameter, then the partial view can't be constructed (that's why you are getting that error).
MSDN Documentation here for RenderPartial method.
So even though there are other answers as to what you need to do, here is what is actually happening, so you know in the future.
#Html.RenderPartial("_NovelProfile");
would be the same code as:
#Html.RenderPartial("_NovelProfile", Model)

ListBoxFor within IEnumerable model

My model -
...
public string[] _SelectedCountries { get; set; }
and my view -
#using System.Collections.Concurrent
#using Example.Models
#model IEnumerable<Example.Models.vw_SpecialQuestionDefinition>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("Create", "SpecialQuestionDefinition", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Scripts.Render("~/Scripts/SpecialQuestions/Index.js")
<div class="row">
<div class="col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">Host Country</h4>
</div>
<div class="panel-body">
#*#Html.ListBoxFor("countries", null, new { #class = "sqQuestions" })*#
#Html.ListBoxFor(model => model._SelectedCountries,
new MultiSelectList((List<SelectListItem>)ViewData["countries"], "Value", "Text"),
new { style = "display:block;", #class = "sqQuestions" })
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-5 col-md-12">
<input type="submit" value="Configure" class="btn btn-default"/>
</div>
</div>
<input type="hidden" name="specialQuestionsId" id="specialQuestionsId" value="-1" />
<input type="hidden" name="answerTypesId" id="answerTypesId" value="-1" />
<input type="hidden" name="hostCountrysId" id="hostCountrysId" value="-1" />
<input type="hidden" name="nationalitysId" id="nationalitysId" value="-1" />
<input type="hidden" name="scopeTypesId" id="scopeTypesId" value="-1" />
}
<h4>Special Question Definition</h4>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Question)
</th>
<th>
#Html.DisplayNameFor(model => model.AnswerType)
</th>
<th>
#Html.DisplayNameFor(model => model.LookupTable)
</th>
<th>
#Html.DisplayNameFor(model => model.CountryName)
</th>
<th>
#Html.DisplayNameFor(model => model.NationalityName)
</th>
<th>
#Html.DisplayNameFor(model => model.ScopeType)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Question)
</td>
<td>
#Html.DisplayFor(modelItem => item.AnswerType)
</td>
<td>
#Html.DisplayFor(modelItem => item.LookupTable)
</td>
<td>
#Html.DisplayFor(modelItem => item.CountryName)
</td>
<td>
#Html.DisplayFor(modelItem => item.NationalityName)
</td>
<td>
#Html.DisplayFor(modelItem => item.ScopeType)
</td>
</tr>
}
</table>
and within my controller -
List<SelectListItem> listCountriesSelectListItems = new List<SelectListItem>();
listSpecialQuestionsSelectListItems.Add(new SelectListItem() { Text = "All", Value = "-1" });
foreach (Country co in db.Countries.OrderBy(c => c.CountryName))
{
SelectListItem selectList = new SelectListItem()
{
Text = co.CountryName,
Value = co.CountryId.ToString()
};
listCountriesSelectListItems.Add(selectList);
}
ViewBag.countries = listCountriesSelectListItems;
so when I run the application, I get this error for my ListBoxFor -
'System.Collections.Generic.IEnumerable<Example.Models.vw_SpecialQuestionDefinition>' does not contain a definition for '_SelectedCountries' and no extension method '_SelectedCountries' accepting a first argument of type 'System.Collections.Generic.IEnumerable<Example.Models.vw_SpecialQuestionDefinition>' could be found (are you missing a using directive or an assembly reference?)
And I believe I understand why I get that error. Because I am trying to treat the model within the view as a single object, when in actuality it's of type IEnumerable<Example.Models.vw_SpecialQuestionDefinition>.
How do I get to _SelectedCountries from my model then?
Also, I use an IEnumerable model to populate a table beneath the list box. This list box is outside of the table and has no reason to be inside of it.
EDIT - POSTED entire view.
I am trying to treat the model within the view as a single object,
when in actuality it's of type
IEnumerable.
Your assumption is correct.
How do I get to _SelectedCountries from my model then?
You need a new model and add IEnumerable inside it.
public class SomeViewModel
{
public IEnumerable<vw_SpecialQuestionDefinition>
SpecialQuestionDefinitions { get; set; }
public string[] _SelectedCountries { get; set; }
}
Then foreach will finally like this -
#foreach (var item in Model.SpecialQuestionDefinitions)

Categories

Resources