Using sql command with controller in view - c#

INSERT INTO SaleItem (ProdId, SaleQuantity) SELECT ProdId, BasketProdQuantity FROM Basket;
This is my SQL command and I want to use it with a button on a view. But I don't know how to references method with button on view. And should I use SqlConnection connection = new SqlConnection(connectionString) I already connect my DB with WebConfig and it connected as DefaultConnection.
EDIT:
I'm new at MVC and Web coding so I don't know what to do.
[HttpPost]
public ActionResult Buy(SaleItem saleitem)
{
if (ModelState.IsValid)
{
string query = "INSERT INTO SaleItem (ProdId, SaleQuantity) SELECT ProdId, BasketProdQuantity FROM Basket";
db.Database.ExecuteSqlCommand(query);
db.SaveChanges();
return RedirectToAction("Index", "Basket");
}
return View(saleitem);
}
and there is the view that I want to use buy method.
#model IEnumerable<VeriPark001.Models.Basket>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Product.Book.BookName)
</th>
<th>
#Html.DisplayNameFor(model => model.BasketProdQuantity)
</th>
<th>
#Html.DisplayNameFor(model => model.Product.ProdPrice)
</th>
<th>
Total
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Product.Book.BookName)
#Html.DisplayFor(modelItem => item.Product.MovieDVD.DVDName)
#Html.DisplayFor(modelItem => item.Product.MusicCD.CDName)
</td>
<td>
#Html.DisplayFor(modelItem => item.BasketProdQuantity)
</td>
<td>
#Html.DisplayFor(modelItem => item.Product.ProdPrice)
</td>
<td>
#(item.Product.ProdPrice * item.BasketProdQuantity)
</td>
<td>
<button>#Html.ActionLink("Delete", "Delete", new { id = item.BasketId })</button>
<button>#Html.ActionLink("Update quantity", "Edit", new { id = item.BasketId })</button>
</td>
</tr>
}
</table>
<p>
<button>I WANT TO CALL ACTION HERE. I search for how to do that and couldn't find a proper way.</button>
<button>#Html.ActionLink("Products", "Index", "Product")</button>
</p>

You can use Html.BeginForm and send a post request to your controller action.
Replace your
<p>
<button>I WANT TO CALL ACTION HERE. I search for how to do that and couldn't find a proper way.</button>
<button>#Html.ActionLink("Products", "Index", "Product")</button>
</p>
with
#using (Html.BeginForm("Buy", "YourController", FormMethod.Post))
{
// Input for your SaleItem model
<button class="btn btn-group btn-group-sm" type="submit">Submit</button>
}
Since your Buy action requires a SaleItem model I'll leave it up to you.

Related

I am receiving a Server error on on the controller on my ASP.NET MVC app

I have an ASP.NET MVC application that I have created. The data displays fine however I get an error which you can see below:
I have created the views and controllers fine however on 2 out of the 5 views / index there is an issue when performing a search via the controller I get an error.
Below is the search functionality I have added to the controller
public AppSupportEntities db = new AppSupportEntities();
// GET: Servers
public ActionResult Index(string searchBy, string search)
{
if (searchBy == "NAME")
{
return View(db.Servers.Where(x => x.NAME.StartsWith(search) || search == null).ToList());
}
else
{
return View(db.Servers.Where(x => x.DESCRIPTION.StartsWith(search) || search == null).ToList());
}
}
This is the search functionality added to the index page on the view
#model IEnumerable<ADSTrepo.Models.Server>
#{
ViewBag.Title = "Index";
}
<h2>Server List</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<p>
#using (Html.BeginForm("Index", "Server", FormMethod.Get))
{
<b>Search By:</b> #Html.RadioButton("searchBy", "Name") <text>Name</text>
#Html.RadioButton("searchBy", "Description") <text>Description</text>
#Html.TextBox("Search")<input type="submit" value="Search" />
}
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.NAME)
</th>
<th>
#Html.DisplayNameFor(model => model.DESCRIPTION)
</th>
<th></th>
</tr>
#if (Model.Count() == 0)
{
<tr>
<td colspan="2"> No rows match the search criteria please try again</td>
</tr>
}
else
{
foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.NAME)
</td>
<td>
#Html.DisplayFor(modelItem => item.DESCRIPTION)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
#Html.ActionLink("Details", "Details", new { id = item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
</tr>
}
}
</table>
Any help is greatly appreciated I must be missing something obvious however the views and controllers seem fine and the same as the others that are working
This has been resolved now. The searchy by name in my controller was different to whats in my view.

Whats the best way of using ajax jquery to load partial views onto a specific page?

I have a index page the code looks like this
#model PagedList.IPagedList<PartialViews.Models.Customer>
#using PagedList.Mvc
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<div class="container">
<table class="table">
<tr>
<th>
Title
</th>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Email Address
</th>
<th>
Phone Number
</th>
<th>
Modified Date
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmailAddress)
</td>
<td>
#Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
#Html.DisplayFor(modelItem => item.ModifiedDate)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.CustomerID }) |
#Html.ActionLink("Details", "Details", new { id = item.CustomerID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.CustomerID })
</td>
</tr>
}
</table>
#Html.PagedListPager(Model,page=>Url.Action("Index",new{page,pageSize=Model.PageSize}))
</div>
My CustomersController has this code
private AdventureWorksLT2012Entities db = new AdventureWorksLT2012Entities();
// GET: Customers
public ActionResult Index(int page=1, int pageSize=10)
{
List<Customer> customers = db.Customers.ToList();
PagedList<Customer> cust = new PagedList<Customer>(customers,page,pageSize);
return View(cust);
//return View(db.Customers.ToList());
}
Heres the Main page where i want the Customers List from the Index action to be shown
#model PartialViews.Models.Customer
#{
ViewBag.Title = "Main";
}
<body>
<div class="container">
<h2>Customer's List</h2>
<div id="dvCustomerDetails" style="width: 50%; height: 130px;display: none"></div>
</div>
</body>
<script type="text/javascript">
$.ajax({
url: 'Customers/Index',
contentType: 'application/html;',
type: 'GET',
dataType:'html'
})
.success(function(result) {
$('#dvCustomerDetails').html(result);
})
</script>
I want to display this table onto a new page as a partial view using ajax jquery but I am having trouble implementing it.
I was able to use RenderPartial method to display it as a partial view but i am having trouble doing it with ajax. Any help or suggestion will be appreciated.

c# - How can I filter the table based on a dropdown selection in mvc application and then display the data?

I am doing my first ever mvc application and I am kind of stuck. What I'm trying to do is filter the existing table based on the selection from the dropdown list.
I have a Course table and a Teacher table and I'd like to be able to filter the Courses by who is teaching them.
This is my controller so far:
namespace TTimetable.Controllers
{
public class CoursesController : Controller
{
private TimetabledbEntities db = new TimetabledbEntities();
// GET: Courses
public ActionResult Index(int teacher)
{
ViewBag.Teacher = new SelectList(db.Teacher, "teacher_Id", "lastName");
var course = db.Course.Include(c => c.Classroom).Include(c => c.Teacher);
return View(course.ToList());
}
This is my View:
#model IEnumerable<TTimetable.Models.Course>
#{
ViewBag.Title = "Courses";
}
<h2>Courses</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.name)
</th>
<th>
#Html.DisplayNameFor(model => model.course_start)
</th>
<th>
#Html.DisplayNameFor(model => model.course_end)
</th>
<th>
#Html.DisplayNameFor(model => model.Classroom.classroom_no)
</th>
<th>
teacher
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.course_start)
</td>
<td>
#Html.DisplayFor(modelItem => item.course_end)
</td>
<td>
#Html.DisplayFor(modelItem => item.Classroom.classroom_no)
</td>
<td>
#Html.DisplayFor(modelItem => item.Teacher.firstName)
</td>
</tr>
}
</table>
<h2>Courses taught by:</h2>
#Html.DropDownList("Teacher", "Select teacher")
So far I was only able to make the dropdown list display the teachers from the database. Anyone who could help me with this? It'll be much appreciated. Thanks
You will need to have your dropdown list post back to the server. This can be accomplished by wrapping the dropdown in a form, and adding javascript to submit the form:
using (Html.BeginForm("Index", "Courses", FormMethod.Get))
{
Html.DropDownList("Teacher", ViewBag.Teacher, "Select teacher", new { onchange = #"form.submit();" });
}
Suggest you to use to Odata approach , when you have multiple filters , for a single table . It will be easy for you in the future.
http://www.c-sharpcorner.com/UploadFile/4d9083/creating-simple-cascading-dropdownlist-in-mvc-4-using-razor/
combining both the techniques can help you.
here viewbag should be casted as it is dynamic type object.
#Html.DropDownList("Teacher", (SelectList)ViewBag.Teacher, "Select teacher", new { onchange = #"form.submit();" });
hope it helps for your solution.

Model Collections Lost When Form Submitted

Using the post request below the model returns null for both the collections yet it correctly returns the boolean attribute. My expectation was that the collections loaded into the model during the get request would persist to the post request. What am I missing?
EDIT: Essentially I am trying to update the list of invoices based on the users selection of a selectlist and a checkbox.
Controller:
[HttpGet]
[AllowAnonymous]
public async Task<ActionResult> Index(bool displayFalse = true)
{
InvoiceViewModel invoiceView = new InvoiceViewModel();
var companies = new SelectList(await DbContext.Company.ToListAsync(), "CompanyID", "Name").ToList();
var invoices = await DbContext.Invoice.Where(s => s.Paid.Equals(displayFalse)).ToListAsync();
return View(new InvoiceViewModel { Companies = companies,Invoices = invoices, SelectedCompanyID = 0, DisplayPaid = displayFalse});
}
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Index(InvoiceViewModel model)
{
model.Invoices = await DbContext.Invoice.Where(s => s.CompanyID.Equals(model.SelectedCompanyID) && s.Paid.Equals(model.DisplayPaid)).ToListAsync();
return View(model);
}
Model:
public class InvoiceViewModel
{
public int SelectedCompanyID { get; set; }
public bool DisplayPaid { get; set; }
public ICollection<SelectListItem> Companies { get; set; }
public ICollection<Invoice> Invoices{ get; set; }
}
View:
#model InvoiceIT.Models.InvoiceViewModel
<form asp-controller="Billing" asp-action="Index" method="post" class="form-horizontal" role="form">
<label for="companyFilter">Filter Company</label>
<select asp-for="SelectedCompanyID" asp-items="Model.Companies" name="companyFilter" class="form-control"></select>
<div class="checkbox">
<label>
<input type="checkbox" asp-for="DisplayPaid" />Display Paid
<input type="submit" value="Filter" class="btn btn-default" />
</label>
</div>
<br />
</form>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().InvoiceID)
</th>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().CompanyID)
</th>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().Description)
</th>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().InvoiceDate)
</th>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().DueDate)
</th>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().Paid)
</th>
<th></th>
</tr>
#foreach (var item in Model.Invoices)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.InvoiceID)
</td>
<td>
#Html.DisplayFor(modelItem => item.CompanyID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.InvoiceDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.DueDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Paid)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.InvoiceID }) |
#Html.ActionLink("Details", "Index", "InvoiceItem", new { id = item.InvoiceID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.InvoiceID })
</td>
</tr>
}
</table>
A form only posts back the name/value pairs of its controls (input, textarea, select). Since the only 2 controls you generate are for the SelectedCompanyID and DisplayPaid properties of your model, then only those properties will be bound when post.
From your comments, what your really wanting to do is to update the table of invoices based on the values of the selected company and the checkbox.
From a performance point of view, the approach is to use ajax to update just the table of invoices based on the value of your controls.
Create a new controller method that return a partial view of the table rows
public PartialViewResult Invoices(int CompanyID, bool DisplayPaid)
{
// Get the filtered collection
IEnumerable<Invoice> model = DbContext.Invoice.Where(....
return PartialView("_Invoices", model);
}
Note you may want to make the CompanyID parameter nullable and adjust the query if your wanting to initially display unfiltered results
And a partial view _Invoices.cshtml
#model IEnumerable<yourAssembly.Invoice>
#foreach(var item in Model)
{
<tr>
<td>#Html.DisplayFor(m => item.InvoiceID)</td>
.... other table cells
</tr>
}
In the main view
#model yourAssembly.InvoiceViewModel
#Html.BeginForm()) // form may not be necessary if you don't have validation attributes
{
#Html.DropDownListFor(m => m.SelectedCompanyID, Model.Companies)
#Html.CheckboxFor(m => m.DisplayPaid)
<button id="filter" type="button">Filter results</button>
}
<table>
<thead>
....
</thead>
<tbody id="invoices">
// If you want to initially display some rows
#Html.Action("Invoices", new { CompanyID = someValue, DisplayPaid = someValue })
</tbody>
</table>
<script>
var url = '#Url.Action("Invoices")';
var table = $('#invoices');
$('#filter').click(function() {
var companyID = $('#SelectedCompanyID').val();
var isDisplayPaid = $('#DisplayPaid').is(':checked');
$.get(url, { CompanyID: companyID, DisplayPaid: isDisplayPaid }, function (html) {
table.append(html);
});
});
</script>
The alternative would be to post the form as your are, but rather than returning the view, use
return RedirectToAction("Invoice", new { companyID = model.SelectedCompanyID, DisplayPaid = model.DisplayPaid });
and modify the GET method to accept the additional parameter.
Side note: Your using the TagHelpers to generate
select asp-for="SelectedCompanyID" asp-items="Model.Companies" name="companyFilter" class="form-control"></select>
I'm not familiar enough with them to be certain, but if name="companyFilter" works (and overrides the default name which would be name="SelectedCompanyID"), then you generating a name attribute which does not match your model property and as a result SelectedCompanyID would be 0 (the default for int) in the POST method.
Appending ToList() to the statement that populates companies is converting the SelectList into a List<T>, which the form will not recognize as a SelectList. Also, by using the dynamic var keyword, you are masking this problem. Try this instead:
SelectList companies = new SelectList(await DbContext.Company.ToListAsync(), "CompanyID", "Name");
In general, try to avoid use of var unless the type is truly dynamic (unknown until runtime).
You put your model data out of form, so it would not submited!
<form asp-controller="Billing" asp-action="Index" method="post" class="form-horizontal" role="form">
<label for="companyFilter">Filter Company</label>
<select asp-for="SelectedCompanyID" asp-items="Model.Companies" name="companyFilter" class="form-control"></select>
<div class="checkbox">
<label>
<input type="checkbox" asp-for="DisplayPaid" />Display Paid
<input type="submit" value="Filter" class="btn btn-default" />
</label>
</div>
<br />
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().InvoiceID)
</th>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().CompanyID)
</th>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().Description)
</th>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().InvoiceDate)
</th>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().DueDate)
</th>
<th>
#Html.DisplayNameFor(model => model.Invoices.FirstOrDefault().Paid)
</th>
<th></th>
</tr>
#foreach (var item in Model.Invoices)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.InvoiceID)
</td>
<td>
#Html.DisplayFor(modelItem => item.CompanyID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.InvoiceDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.DueDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Paid)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.InvoiceID }) |
#Html.ActionLink("Details", "Index", "InvoiceItem", new { id = item.InvoiceID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.InvoiceID })
</td>
</tr>
}
</table>
</form>
Using a for loop to create the with the companies will make it possible to map back and persist the company values
for(c = 0 ; c < Model.Companies.Count(); c++)
{
<input type='hidden' name='#Html.NameFor(Model.Companies[c].Propery1)' id='#Html.IdFor(Model.Comapnies[c].Propery1)' value='somevalue'>someText />
<input type='hidden' name='#Html.NameFor(Model.Companies[c].Propery2)' id='#Html.IdFor(Model.Comapnies[c].Propery2)' value='somevalue'>someText />
}
this ensures that the list is mapped back as the default model binder expects list to be in ListProperty[index] format

Pass ViewModel to ActionResult mvc4

I have a view that the model is IEnumerable. the view is the mvc basic view that is created upon creating new controller with read write actions.
I do not want that the edit action will call a different view, i want to add a button in the index view that by pressing the button in a specific row the button will call the action result with the model that was "pressed" and from there the logic will continue.
The View
#model IEnumerable<V1_ILotto.Areas.Admin.Models.WithdrawalModel>
#{
ViewBag.Title = "בקשות משיכה";
}
<h2>בקשות משיכה</h2>
#using (Html.BeginForm("Approve", "Withdrawals", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.User)
</th>
<th>
#Html.DisplayNameFor(model => model.WithdrawalAmount)
</th>
<th>
#Html.DisplayNameFor(model => model.Balance)
</th>
<th>
#Html.DisplayNameFor(model => model.IsApproved)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.User)
</td>
<td>
#Html.DisplayFor(modelItem => item.WithdrawalAmount)
</td>
<td>
#Html.DisplayFor(modelItem => item.Balance)
</td>
<td>
<p>
<input type="submit" value="Submit" />
</p>
</td>
</tr>
}
</table>
}
The Controller
[HttpPost]
public ActionResult Approve(WithdrawalModel withdrawalmodel)
{
if (ModelState.IsValid)
{
//logic for updating the db
return RedirectToAction("Index");
}
return View(withdrawalmodel);
}
Note : the view is in not getting a single model but IEnumerable of that model
only for helpers (except display) tie the data to the model. If you want data passed back you need to put your values in at least a hidden for
#Html.HiddenFor(x => x.Balance)
etc

Categories

Resources