How to call method on the Controller from view - asp.net

First of all I'm a little new on this and I have a lot of questions but one of them is the next one.
Is there any way to call methods (without view) situated on the Controller from another view and send one parameter at the same time?
I've been trying to do it but I can't.
I have tried this:
#{
((HomeController)this.ViewContext.Controller).Method1();
}
but I get an error which says that namespace could not be found
the flow is: open the view->click on add button->select one row from other table->through coding, send the Id of the product to the method I need in order to find a product and insert it into my new table.
here you have some code.
First View
<div id="lista" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
#{Html.RenderAction("selectOrden", "Producto");}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cerrar</button>
</div>
</div>
</div>
</div>
Controller
[HttpGet]
public ActionResult selectOrden()
{
try
{
client = new FireSharp.FirebaseClient(config);
FirebaseResponse response = client.Get("Producto");
dynamic data = JsonConvert.DeserializeObject<dynamic>(response.Body);
var list = new List<Producto>();
foreach (var item in data)
{
list.Add(JsonConvert.DeserializeObject<Producto>(((JProperty)item).Value.ToString()));
Debug.WriteLine(JsonConvert.DeserializeObject<Producto>(((JProperty)item).Value.ToString()).nombreProducto);
return View(list);
}
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, ex.Message);
}
return View();
}
//Inserta registros de productos en las ordenes de compra
[HttpPost]
public void selectOrdena(string id)
{
client = new FireSharp.FirebaseClient(config);
FirebaseResponse responseProdu = client.Get("Producto/" + id);
Producto dataProdu = JsonConvert.DeserializeObject<Producto>(responseProdu.Body);
ViewBag.Soli = dataProdu;
Debug.WriteLine("Hello");
//return View(dataProdu);
}
Second View
#model IEnumerable<FirebaseMVCTestApp.Models.Producto>
#{
ViewBag.Title = "selectOrden";
Layout = null;
}
<h2>selectOrden</h2>
#using (Html.BeginForm("Save","ProductoController", FormMethod.Post))
{
<form method="post">
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<table id="table_idxd" class="display">
<thead>
<tr>
<th>
Nombre del producto
</th>
<th>
Cantidad
</th>
<th>
Costo
</th>
<th>
Precio
</th>
<th>
Codigo
</th>
<th>Acción</th>
</tr>
</thead>
#{ try
{
foreach (var item in Model)
{
<tr>
<td>
#Html.EditorFor(model => item.nombreProducto, new { htmlAttributes = new { #class = "form-control" } })
</td>
<td>
#Html.EditorFor(modelItem => item.cantidad, new { htmlAttributes = new { #class = "form-control" } })
</td>
<td>
#Html.EditorFor(modelItem => item.costo, new { htmlAttributes = new { #class = "form-control" } })
</td>
<td>
#Html.EditorFor(modelItem => item.precio, new { htmlAttributes = new { #class = "form-control" } })
</td>
<td>
#Html.EditorFor(modelItem => item.codigo, new { htmlAttributes = new { #class = "form-control" } })
</td>
<td>
#Html.ActionLink("Agregar", "selectOrdena", new { id = item.idProducto })
<input type="submit" value="Save" class="btn btn-default" />
</td>
</tr>
}
}
catch (Exception ex)
{
}
}
</table>
</form>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>

The method you provided is valid.
This is how you call an instance method on the Controller:
#{
((HomeController)this.ViewContext.Controller).Method1();
}
This is how you call a static method in any class:
#{
SomeClass.Method();
}
This will work assuming the method is public and visible to the view.But according to what you said, an error was reported:
that namespace could not be found
The reason may be that the project that references the assembly may have a different frame type from the assembly.You can check this post, it may be helpful to you:https://stackoverflow.com/questions/4764978/the-type-or-namespace-name-could-not-be-found

Ok I've checked all the other threads and I think it was going so far from my problem, but I have already solved it by adding this line on the second view
#using FirebaseMVCTestApp.Controllers
in that way the view could see the controller I needed.
I know that the question was a little newbbie but if I didn't ask I would probably never find the answer.
Thank you. :)

Related

Renderpartial in a foreach loop only sends the first element in list

I'm trying to send a User in a list of users to a partial view but the partial view only takes the first user in the list. The code correctly displays the username and the actionlink to profile but for some reason only the first user in the list is sent to the partial view in every iteration.
What I want to do is to dynamically show the "confirmDelete" partial view when the delete button is clicked and delete the correct user.
Help is appreciated!
Edit:
I think I see the problem now, I name the url pointing to the Delete-Action "RedirectTo" in every partial view, and also all the divisions have the same id.. Still don't know how to fix it though.
MainView:
#foreach (var item in ViewBag.UsersList as List<CommonLibrary.User>)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.ActionLink("Profile", "ProfilePage", new { id = item.UserId }) |
#{
var user = Homepage.Service.SessionHelper.GetSessionUser(Context);
if (user != null && user.GetType().ToString() == "CommonLibrary.Operator" && item.UserId != user.UserId)
{
<button id="#item.UserId" class="btn-danger" onclick="confirmDelete()">Delete</button>
<div style="width:40%; float:right;">
#{
await Html.RenderPartialAsync("_ConfirmDelete", item);
}
</div>
}
}
</td>
</tr>
}
Partial View:
#model CommonLibrary.User
#Html.Hidden("RedirectTo", Url.Action("Delete", "Users", new { id = Model.UserId }))
<div style="display:none" id="confDelete">
<div>
<b>Are you sure you want to delete user: #Model.UserName?</b>
</div>
<button id="Yes" class="btn-danger" onclick="deleteConfirmed()">Yes</button>
<button id="No" class="btn-secondary" onclick="hideDelete()">No</button>
</div>
<script>
function confirmDelete() {
$("#confDelete").show();
$("#del_btn").hide();
}
function hideDelete() {
$("#confDelete").hide();
$("#del_btn").show();
}
function deleteConfirmed() {
var url = $("#RedirectTo").val();
location.href = url;
}
</script>
I figured it out by using UserId as id for the different elements.
Main View:
<tbody>
#foreach (var item in ViewBag.UsersList as List<CommonLibrary.User>)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.ActionLink("Profile", "ProfilePage", new { id = item.UserId }) |
#{
var user = Homepage.Service.SessionHelper.GetSessionUser(Context);
if (user != null && user.GetType().ToString() == "CommonLibrary.Operator" && item.UserId != user.UserId)
{
<button id="#item.UserId" class="btn btn-danger" onclick="confirmDelete(this.id)">Delete</button>
<div style="width:40%; float:right;">
#{
await Html.RenderPartialAsync("_ConfirmDelete", item);
}
</div>
}
}
</td>
</tr>
}
</tbody>
</table>
<script>
function confirmDelete(id) {
var element = document.getElementById("div" + id);
element.style.display = "block";
}
function hideDelete(id) {
var element = document.getElementById("div" + id);
element.style.display = "none";
}
function deleteConfirmed(id) {
var url = "/Users/Delete/" + id;
window.location.href = url;
}
</script>
Partial View:
#model CommonLibrary.User
#{
var divId = "div" + Model.UserId.ToString();
}
<div style="display:none" id="#divId">
<div>
<b>Are you sure you want to delete user: #Model.UserName?</b>
</div>
<button id="#Model.UserId.ToString()" class="btn btn-danger" onclick="deleteConfirmed(this.id)">Yes</button>
<button id="#Model.UserId.ToString()" class="btn btn-secondary" onclick="hideDelete(this.id)">No</button>
</div>

How to Post correctly w/ List<Model> from the view to the controller? [duplicate]

I have a HTML table as below in my View:
<table id="tblCurrentYear">
<tr>
<td>Leave Type</td>
<td>Leave Taken</td>
<td>Leave Balance</td>
<td>Leave Total</td>
</tr>
#foreach (var item in Model.LeaveDetailsList)
{
<tr>
<td>#Html.TextBoxFor(m => item.LeaveType, new { width = "100" })</td>
<td>#Html.TextBoxFor(m => item.LeaveTaken, new { width = "100" })</td>
<td>#Html.TextBoxFor(m => item.LeaveBalance, new { width = "100" })</td>
<td>#Html.TextBoxFor(m => item.LeaveTotal, new { width = "100" })</td>
</tr>
}
</table>
I want to iterate through all the html table rows and insert the values in ADO.NET DataTable.
Simple speaking, converting HTML Table to ADO.NET DataTable.
How to extract values from HTML Table and insert into ADO.NET DataTable?
The view is based on the following model
public class LeaveBalanceViewModel
{
public LeaveBalanceViewModel()
{
this.EmployeeDetail = new EmployeeDetails();
this.LeaveBalanceDetail = new LeaveBalanceDetails();
this.LeaveDetailsList = new List<LeaveBalanceDetails>();
}
public EmployeeDetails EmployeeDetail { get; set; }
public LeaveBalanceDetails LeaveBalanceDetail { get; set; }
public List<LeaveBalanceDetails> LeaveDetailsList { get; set; }
}
In order to bind to a model on post back, the name attributes of the form controls must match the model properties. Your use of a foreach loop does not generate the correct name attributes. If you inspect the html you will see multiple instances of
<input type="text" name="item.LeaveType" .../>
but in order to bind to your model the controls would need to be
<input type="text" name="LeaveDetailsList[0].LeaveType" .../>
<input type="text" name="LeaveDetailsList[1].LeaveType" .../>
etc. The easiest way to think about this is to consider how you would access the value of a LeaveType property in C# code
var model = new LeaveBalanceViewModel();
// add some LeaveBalanceDetails instances to the LeaveDetailsList property, then access a value
var leaveType = model.LeaveDetailsList[0].LeaveType;
Since your POST method will have a parameter name (say model), just drop the prefix (model) and that's how the name attribute of the control must be. In order to do that you must use either a for loop (the collection must implement IList<T>)
for(int i = 0; i < Model.LeaveDetailsList.Count; i++)
{
#Html.TextBoxFor(m => m.LeaveDetailsList[i].LeaveType)
....
}
or use a custom EditorTemplate (the collection need only implement IEnumerable<T>)
In /Views/Shared/EditorTemplates/LeaveBalanceDetails.cshtml
#model yourAssembly.LeaveBalanceDetails
<tr>
<td>#Html.TextBoxFor(m => m.LeaveType)</td>
....
</tr>
and then in the main view (not in a loop)
<table>
.... // add headings (preferably in a thead element
<tbody>
#Html.EditorFor(m => m.LeaveDetailsList)
</tbody>
</table>
and finally, in the controller
public ActionResult Edit(LeaveBalanceViewModel model)
{
// iterate over model.LeaveDetailsList and save the items
}
With respect to your requirement, try this
jQuery(document).on("change", ".DDLChoices", function (e) {
var comma_ChoiceIds = '';
var comma_ChoicesText = '';
$('input[class="DDLChoices"]').each(function (e) {
if (this.checked) {
comma_ChoiceIds = comma_ChoiceIds + $(this).val() + ',';
comma_ChoicesText = comma_ChoicesText + $(this).parent('label').parent() + ',';
}
});
$('#ChoiceIds').val(comma_ChoiceIds);
$('#ChoiceText').val(comma_ChoicesText);
});
#using (Html.BeginForm("Actionname", "Controllername", FormMethod.Post, new { id = "frmChoices" }))
{
#Html.HiddenFor(m => m.ChoiceText, new { #id = "ChoiceText" })
#Html.HiddenFor(m => m.ChoiceIds, new { #id = "ChoiceIds" })
<div class="form-group">
<div>
<table>
<tr>
<th>Name</th>
<th>Selected</th>
</tr>
#foreach (var item in #Model.Choices)
{
<tr>
<td> <label>#item.ChoicesText</label> </td>
<td> <input class="DDLChoices" value="#item.ChoiceIds" type="checkbox" /></td>
</tr>
}
</table>
</div>
<input type="button" value="Submit" onclick="return ChoicesPoster.passChoices()"
</div>
}

Updating multiple records at the same time in MVC

Trying to update more than 1 record using a form submission in MVC (bringing existing data into the View from the DB and allowing user to make changes).
In the View, I can return as many existing records as I need ready to be edited, without a problem:
#model IEnumerable<object>
#{
List<Portal.Models.Primary_Client> PClient = Model.ToList()[0] as List<Portal.Models.Primary_Client>;
List<Portal.Models.Primary_Dependent> PDependant = Model.ToList()[1] as List<Portal.Models.Primary_Dependent>;
List<Portal.Models.Primary_AnnExp> PAnnExp = Model.ToList()[2] as List<Portal.Models.Primary_AnnExp>;
List<Portal.Models.Primary_IncExp> PIncEx = Model.ToList()[3] as List<Portal.Models.Primary_IncExp>;
List<Portal.Models.Primary_InvAssets> PInvAssets = Model.ToList()[4] as List<Portal.Models.Primary_InvAssets>;
List<Portal.Models.Primary_Liabilities> PLiabilities = Model.ToList()[5] as List<Portal.Models.Primary_Liabilities>;
List<Portal.Models.Primary_LifeAssets> PLAssets = Model.ToList()[6] as List<Portal.Models.Primary_LifeAssets>;
ViewBag.Title = "Completed Form";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("EditPLA/" + newid, "Forms", FormMethod.Post))
{
for (int i = 0; i < PLAssets.Count; i++)
{
<div class="form-group">
#Html.HiddenFor(Model => PLAssets[i].LifAsset_ID)
#Html.HiddenFor(Model => PLAssets[i].PLForm_ID)
#Html.HiddenFor(Model => PLAssets[i].Client_ID_PriFK)
</div>
<div class="container">
<div class="row">
<div class="col-sm">
#Html.Label("Asset Type")
#Html.EditorFor(Model => PLAssets[i].PLAsset_Type, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="col-sm">
#Html.Label("Asset Amount")
#Html.EditorFor(Model => PLAssets[i].PLAmount_Per_Annum, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
</div>
<br />
}
<div class="button" style="text-align:center;">
<input type="submit" class="btn btn-success" value="Save" />
<button class="btn btn-danger" data-dismiss="modal">Cancel</button>
</div>
}
However, my model does not populate properly when I submit the form as the field names are not passing as expected and do not match my model field names. I suspect this is because of how I create the fields using the loop.
My Editor field names look like this:
<input class="form-control text-box single-line" id="CS___8__locals1_PLAssets_0__PLAmount_Per_Annum" name="CS$<>8__locals1.PLAssets[0].PLAmount_Per_Annum" type="text" value="3">
When I would have expected to see something more like this:
<input class="form-control text-box single-line" id="PLAmount_Per_Annum" name="PLAmount_Per_Annum" type="text" value="3">
I believe this is made more difficult than usual because I have several Models being passed to my View through an Object, but I don't know how else to create these fields with the correct name.
FYI - My Controller looks like this:
[HttpPost]
public ActionResult EditPLA(List<Primary_LifeAssets> Assets, int id)
{
if (ModelState.IsValid)
{
foreach (var i in Assets)
{
var c = db1.Primary_LifeAssets.Where(a => a.LifAsset_ID.Equals(i.LifAsset_ID)).FirstOrDefault();
if (c != null)
{
c.PLForm_ID = i.PLForm_ID;
c.PLAmount_Per_Annum = i.PLAmount_Per_Annum;
c.PLAsset_Type = i.PLAsset_Type;
}
}
db1.Entry(Assets).State = EntityState.Modified;
db1.SaveChanges();
ViewBag.Message = "Successfully Updated.";
return RedirectToAction("Existing/" + id, "Forms");
}
ViewBag.Message = "Save failed.";
return RedirectToAction("Existing/" + id, "Forms");
}

How to retrieve form data and assign it to a text as a url on MVC 4

i would like to return below url from a search submit where id will be get from database.
So when a user search something by id it will search my database and display the result on my home view. then i want to transform my ID a clickable url which is this one:
http://myadress.com:8787/Handlers/DataExport.ashx?format=pdf&id=???&direction=0
Any idea how to do?
This is my home view:
<body>
<p>
#using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
<b>SEARCH BY:</b> #Html.RadioButton("searchby", "ID", true) <text>ID</text>
#Html.RadioButton("searchby", "NAME") <text>NAME</text>
<br /><br />
#Html.TextBox("search") <input type="submit" value="SEARCH" />
}
</p>
<table>
<tr>
<th>
ID
</th>
<th>
NAME
</th>
<th>Actions</th>
</tr>
#if (Model.Count() == 0)
{
<tr>
<td colspan="2">NO DATA FOUND.</td>
</tr>
}
else
{
foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.NAME)
</td>
<td>
#Html.ActionLink("Details", "Details", new { id = item.id })
</td>
</tr>
}
}
this is my controller:
public class HomeController : Controller
{
private mydbEntities db = new mydbEntities();
//
// GET: /Home/
public ActionResult Index(string searchBy, string search)
{
if (searchBy == "ID")
{
return View(db.mytable.Where(x => x.ID == search).ToList());
}
else (searchBy == "NAME")
{
return View(db.mytable.Where(x => x.NAME == search).ToList());
}
}
You could just create an anchor tag and substitute the id in the href attribute
your link text
you have to use jquery for this. something like
$('.btnSearch').on('click', function(){
$('.lnkSubmit').attr('href', '#Url.Action("Action", "Controller", new { id = "----" })'.replace("----", (returned id here));
});
this will replace the url of a link with class lnkSubmit and will include the id that you put in it. Let me know if you have any questions.
In my Blog application, this is how I implemented search functionality for searching posts.
Partial view for search:
#using (Html.BeginForm("Search", "Blog", FormMethod.Get, new {id = "search-form"}))
{
<input type="text" name="s" placeholder="Search">
<button type="submit">Go</button>
}
Search action in controller:
public ActionResult Search(string s)
{
var model = _dbPostRepository.GetPostsForSearch(s);
ViewBag.TotalPosts = _dbPostRepository.TotalSearchPosts(s);
return View("Posts");
}
Posts View:
#model FirstBlog.Core.Post
#if (#ViewBag.TotalPosts > 0)
{
foreach (var item in Model)
{
Html.RenderPartial("_PostTemplate", item);
}
}
else
{
<p>No posts found!</p>
}
_PostTemplate is the view for each post. Hope this would help.

Custom Filename for #Html.EditorForModel()?

so I have the following code:
#model IEnumerable<My_School_Book.Models.Mark>
#{
ViewBag.Title = "Marks";
}
<div class="row-fluid">
<h1>Assignment Marks:</h1>
#using (Html.BeginForm("Marks", "Assignment", FormMethod.Post, new { #class = "form-horizontal" }))
{
<table class="table table-bordered">
<thead>
<tr>
<th>Student</th>
<th style="width: 50px;">Mark
</th>
<th style="width: 50px;">Total
</th>
<th style="width: 50px;">Weight</th>
</tr>
</thead>
<tbody>
#Html.EditorForModel()
</tbody>
</table>
<div class="form-actions">
<button type="submit" class="btn btn-primary"><i class="icon-checkmark"></i> Save</button>
<i class="icon-back"></i> Cancel
</div>
}
</div>
As you can see my Model being passed into the view is an IEnumerable of the Model Mark.
Now I have a EditorTemplate under the Views/Shared folder called Mark:
#model My_School_Book.Models.Mark
<tr>
<td>#Model.Student.FullName</td>
<td>
#Html.TextBoxFor(model => Model.Grade, new { #class = "span12", #style = "min-height: 20px;", #maxlength = "5" })
</td>
<td>
#Model.Assignment.Total
</td>
<td>#Model.Assignment.Weight</td>
</tr>
My question is, can I rename my EditorTemplate file from Mark to AssignmentMarks? I'd like it to be more specific instead of a generic name called Marks.
Edit:
Inside my MarkRepository.cs
public IEnumerable<Mark> GetAllByAssignmentID(Guid id)
{
return context.Marks.Where(m => m.AssignmentID == id);
}
Inside my AssignmentController.cs
public ActionResult Marks(Guid id)
{
IEnumerable<Mark> Marks = markRepository.GetAllByAssignmentID(id).ToList();
return View(Marks);
}
[HttpPost]
public ActionResult Marks(IEnumerable<Mark> viewModel)
{
if (ModelState.IsValid)
{
}
return View(viewModel);
}
Inside my Marks.cshtml
#Html.EditorForModel("Mark", "AssignmentMark")
Inside my AssignmentMark.cshtml
#model My_School_Book.Models.Mark
<tr>
<td>#Html.DisplayTextFor(model => model.Student.FullName)</td>
<td>#Html.TextBoxFor(model => model.Grade, new { #class = "span12" })</td>
<td>#Html.DisplayTextFor(model => model.Assignment.Total)</td>
<td>#Html.DisplayTextFor(model => model.Assignment.Weight)</td>
</tr>
The error I receive on my View is now:
System.Data.Entity.DynamicProxies.Assignment_7EDE7AD8477AB363802A036747CD8A8B259C6CD72DCEF587A2B0FBEDC7B2DCE1System.Data.Entity.DynamicProxies.Assignment_7EDE7AD8477AB363802A036747CD8A8B259C6CD72DCEF587A2B0FBEDC7B2DCE1System.Data.Entity.DynamicProxies.Assignment_7EDE7AD8477AB363802A036747CD8A8B259C6CD72DCEF587A2B0FBEDC7B2DCE1System.Data.Entity.DynamicProxies.Assignment_7EDE7AD8477AB363802A036747CD8A8B259C6CD72DCEF587A2B0FBEDC7B2DCE1
Rename your model class to be AssignmentMarks
Instead of #EditorForModel(), run the following:
#foreach(var mark in Model)
{
#EditorFor(m => m.Mark, "AssignmentMark")
}
Hope this will help you.

Resources