I work on asp mvc5 project.
I have this view:
#using (Html.BeginForm("About", "Home", FormMethod.Post, new { id = "myForm", #class = "btn btn-featured btn-white" }))
{
foreach (var item in Model)
{
<tr>
<td>
<a href="javascript:document.getElementById('myForm').submit()">
<span class="hidden">#Html.Raw(Json.Encode(item))</span>
<span>#item.Name</span>
</a>
</td>
</tr>
}
}
as ypu can see I have this row in view above:
#Html.Raw(Json.Encode(item))
And here is action method:
[Authorize]
[HttpPost]
public ActionResult About(FormCollection objViewDataModel )
{
//some logic
return View(userGroup);
}
when I click on anchor tag on the view the action methos About is fired in controller, I need to access
to hidden span control but I dont see it in my objViewDataModel.
Any idea what I do wrong and how to access JSON inside hidden span control?
If you want something to be posted in a form, it should be in an input element, not a span.
So change <span class="hidden" to <input type="hidden" and give it a name.
Related
I am new to Asp.Net Mvc. I couldn't find a solution that worked for me here, if I am blind just redirect me.
I am trying to make a web-app where i can search through clients, without displaying the entire table of clients. Only after the user presses search, the search result should show as a partial view. I understand that using Ajax is the most popular way of handling something like this.
Any pointers on how to accomplish this?
My first thought was to just make a display: block/none script connected to the submit button but the page updates each time you search rendering this idea useless. That's why i could use some help with how to asynchronously update the web page with the search result.
HomeController:
using testForAutofill.Models;
//Search Functionality
[HttpPost]
public PartialViewResult Index(string searchTerm)
{
test_Db_Context db = test_Db_Context();
List<ViewNewOrderSum> orderSums;
if (string.IsNullOrEmpty(searchTerm))//Fix this.
{
orderSums = db.ViewNewOrderSum.ToList();
}
else
{
orderSums = db.ViewNewOrderSum.Where(x =>
x.ClientName.Equals(searchTerm)).ToList();
}
return PartialView(orderSums);
}
Index View:
#model IEnumerable<testForAutofill.Models.ViewNewOrderSum>
#using (Html.BeginForm())
{
<b>Kundenavn:</b>
#Html.TextBox("searchTerm", null, new { id = "txtSearch" })
<input type="submit" value="🔍 Search" class="btn btn-primary" id="btn-search" />
}
<div id="posts-wrapper"></div>
<div class="client-div" runat="server" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body" id="client-Card">
<h4 class="card-title">Client info</h4>
<table id="client-table">
<tr>
<th>
#Html.DisplayNameFor(model => model.ClientName)
</th>
</tr>
#foreach (var item in Model)
{
#Html.Partial("_OrderSum", item)
}
</table>
</div>
</div>
Partial View:
#model testForAutofill.Models.ViewNewOrderSum
<tr>
<td>
#Html.DisplayFor(modelItem => Model.ClientName)
</td>
</tr>
No need of using Ajax. You can submit search text in Form Post. Fetch your data and filter based on your searchTerm retun to View with model. If your model is not null or empty show table else do not display table.
Checkout the below code :
View :
#model List<testForAutofill.Models.ViewNewOrderSum>
#using (Html.BeginForm()) {
<b>Kundenavn:</b>
#Html.TextBox("searchTerm", null, new { id = "txtSearch" })
<input type="submit" value="🔍 Search" class="btn btn-primary" id="btn-search" />
}
#if (Model != null && Model.Count() > 0) {
<div class="client-div" runat="server" style="max-width: 20rem;">
<div class="card-header">Header</div>
<div class="card-body" id="client-Card">
<h4 class="card-title">Client info</h4>
<table id="client-table">
<tr>
<th>
ClientName
</th>
</tr>
#foreach (var item in Model) {
#Html.Partial("_OrderSum", item)
}
</table>
</div>
</div>
}
Controller :
public ActionResult Index()
{
//if you want to load all the clients by default
test_Db_Context db = test_Db_Context();
List<ViewNewOrderSum> orderSums;
orderSums = db.ViewNewOrderSum.ToList();
return View(orderSums);
}
[HttpPost]
public ActionResult Index(string searchTerm) {
test_Db_Context db = test_Db_Context();
List<ViewNewOrderSum> orderSums;
if (!string.IsNullOrEmpty(searchTerm))
{
orderSums = db.ViewNewOrderSum.Where(x =>
x.ClientName.Equals(searchTerm)).ToList();
}
return View(result);
}
My first thought was to just make a display: block/none script
connected to the submit button but the page updates each time you
search rendering this idea useless.
You can prevent the page from updating using something like the following (using jQuery):
<script type="text/javascript">
$('form').submit(function (evt) {
evt.preventDefault();
... your code
});
</script>
Then you can make your ajax POST call, get the data, unhide table headers and append the html results from your partial view.
My application searches for the files that contains a string the user is looking for. So far it does that perfectly. The last thing I need to do is to export it to an excel file so I added a method inside of my controller that is called by the Result page after I press a button.
The results are stored in a List of type Result which is a class with four variables.
The method ExportToExcel currently returns string so that I can test if the list of results is null. Every single time it has come out as "No Data", therefore it is null. It perfectly prints out a table with the information in the Results page but does not have the information when i want to export it.
Why is my model not passing from view to method?
At first I wanted to pass my model so that I can access the information in the List but now I am wondering if it would be better to save the List data in the controller so that I can directly pass it to my method.
Either way would be fine and I am open to any other ways to do this.
Model
namespace Final.Models
{
public class InputModel:Result
{
public List<Result> Results { get; set; }
}
}
Controller
This controller is just showing how I am passing the InputModel between the views and method. Maybe I am doing something wrong here?
public ActionResult Index()
{
var input = new InputModel();
return View(input);
}
[HttpPost]
public ActionResult Index(InputModel input)
{
//Finds files that contain string.
//send model to Result
return View("Result", input);
}
public ActionResult Result(InputModel input)
{
return View(input);
}
[HttpPost]
public string Result(InputModel input,string export)
{
return ExportToExcel(input);
}
public string ExportToExcel(InputModel input)
{
if (input.Results!=null)
{
//Run excel code here
return "Excel Exported";
}
else
{
return "No Data";
}
}
View for Result
This is part of the view, not the whole thing. I didn't think the full view was necessary but I posted it in the bottom just in case.
#foreach(var result in Model.Results)
{
<tr>
//Return graph of information received
</tr>
}
</table>
<form action="Find/Result" method="POST">
<input type="submit" value="Export" name="export" class="btn btn-default">
</form>
Output
Occurs after pressing the "Export" Button
"No Data"
This is my first MVC applications so once again please let me know if there is any other area I can improve in.
Full View For Result
Changed the form to enclose the entire view as suggested by Wubbly but I get the same output.
#model Final.Models.InputModel
#{
ViewBag.Title = "Result";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<br />
<h4>Result</h4>
<hr />
#using (Html.BeginForm("Result", "Find", FormMethod.Post))
{
<p>The <b>#Model.SelectedText</b> files that contain <b>"#Model.Find"</b> are: </p>
<div>
<table class="table table-bordered table-responsive table-hover">
<tr>
//HEADERS
</tr>
#foreach (var result in Model.Results)
{
// int i = 1;
<tr>
<td>#result.SelectedText</td>
<td>#result.FileName</td>
<td>#result.Line</td>
<td>#result.LineCode</td>
</tr>
}
</table>
<div class="form-group">
<div class="col-md-offset-2 ">
<input type="submit" value="Export" name="export" class="btn btn-default">
</div>
</div>
</div>
}
<p>
#Html.ActionLink("Back to List", "Index")
</p>
Use for loop with hidden property which takes your property value to model.
#using (Html.BeginForm("Result", "Find", FormMethod.Post))
{
<p>The <b>#Model.SelectedText</b> files that contain <b>"#Model.Find"</b> are: </p>
<div>
<table class="table table-bordered table-responsive table-hover">
<tr>
//HEADERS
</tr>
#for (int i = 0; i < Model.Results.Count; i++)
{
// int i = 1;
<tr>
<td>
#Html.HiddenFor(r => r.Model.Results[i].SelectedText)
#Html.HiddenFor(r => r.Model.Results[i].FileName)
#Html.HiddenFor(r => r.Model.Results[i].Line)
#Html.HiddenFor(r => r.Model.Results[i].LineCode)
#Html.DisplayFor(r => r.Model.Results[i].SelectedText)
</td>
<td>#Html.DisplayFor(r => r.Model.Results[i].FileName)</td>
<td>#Html.DisplayFor(r => r.Model.Results[i].Line)</td>
<td>#Html.DisplayFor(r => r.Model.Results[i].LineCode)</td>
</tr>
}
</table>
<div class="form-group">
<div class="col-md-offset-2 ">
<input type="submit" value="Export" name="export" class="btn btn-default">
</div>
</div>
</div>
}
<p>
#Html.ActionLink("Back to List", "Index")
</p>
To anyone who might need an answer and is in a similar situation I figured my problem out. Many of you might not think it is the right way to fix it but it is what worked for me. Either way any feedback would be appreciated to improve my abilities.
First, I did change my foreach to a for loop as recommended by StephenMuecke and ShailendraKumar.
The way I transferred the data from my HTTPGet to my HTTPPostis with TempData. I used it to store my model with the user's input inside my HTTPPost Index and called it in my HTTPPost Result.
Here's how I changed my controller.
public ActionResult Index()
{
var input = new InputModel();
input.Type = input.FillType(input.Type);
return View(input);
}
[HttpPost]
public ActionResult Index(InputModel input)
{
input.FileType = input.ValueConvert();
input.FileFind();
TempData["model"] = input
return View("Result", input);
}
public ActionResult Result(InputModel input)
{
return View(input);
}
[HttpPost]
public void Result()
{
InputModel model = new InputModel();
model = (InputModel)TempData["model"];
model.ExportToExcel();
}
In my index page, i have multiple checkboxes that can be selected:
#foreach (var item in Model) {
<tr>
<td class ="text-nowrap">
<input class="chkSelect" type="checkbox" name="Selected" value="#item.Id">
</td>
<td>
#Html.ValueFor(modelItem => item.trandate, "{0:dd/MM/yyyy}")
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.Id })
</td>
</tr>
}
I need to get the selected items and pass them to another form/page /action where i want to use the ids of the selected item to perform other actions.
How do i pass the selected items to the controller action of the other page ?
so , now i created public ActionResult SendSMS(string[] msisdn)
{
return View();
}
and
#using (Html.BeginForm("SendSMS", "Subscribers", FormMethod.Post))
{
<div class="form-group">
<span class="btn btn-primary"> <i class="fa fa-envelope"></i> Send SMS</span>
</div>
}
So, will Request["Selected"] hold all the selected items? it appears null when debugging.
You could POST it to the controller and do a redirect with those values. The values would then do in a query strings to the other action. Like:
return RedirectToAction("Index", "Home", new { value1 = value1, value2 = value 2});
I was able to get this done by simply using a submit button. and
and in the controller action SendSMS i have :
if (Request["Selected"] != null)
{
model.msisdn = string.Empty;
model.MessageId = string.Empty;
foreach (var selection in Request["Selected"].Split(','))
{
}
}
I'm going crazy on this... I've been trying to figure out how to use ajax to update a partial view for quite some time... I've got to be missing something simple and easy.
I'm in VS2012, MVC4.
First, I do have these bundles loaded:
#Styles.Render("~/css")
#Styles.Render("~/Content/themes/base/css")
#Scripts.Render("~/js" )
#Scripts.Render("~/bundles/jqueryui")
#Scripts.Render("~/bundles/jqueryval")
I have also tried to specify the unobtrusive script manually as well...
Then I have this in my view:
#using (Ajax.BeginForm("Index_AddGroup", new AjaxOptions { UpdateTargetId = "AddGroupList" }))
{
<div>
#Html.LabelFor(model => Model.NewGroups.GroupName)
</div>
<div>
#Html.DropDownListFor(model => Model.AllGroups.nSelectGroupID, Model.AllGroups.GroupList, "Select Group to Add")
<input type="submit" value="Add Group" />
</div>
}
Then I load a partial view:
<div id="AddGroupList">
#if(Model.Groups != null)
{
#Html.Partial("_AddGroups", Model.Groups);
}
</div>
In that partial view I do the following:
#model IEnumerable<MyApp.ViewModels.Group>
#{
ViewBag.Title = "Added Groups";
}
<h2>Groups to be Added</h2>
<table>
<tr>
<th>Group Name</th>
<th>Added until</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(model=>item.GroupName)</td>
<td>#Html.DisplayFor(model=>item.EndDate)</td>
</tr>
}
Controller:
[HttpPost]
public ActionResult Index_AddGroup(SearchedUser viewModel)
{
AddGroupsContext db = new AddGroupsContext();
Group NewGroup = new Group();
NewGroup.GroupName = "test";//viewModel.
db.Groups.Add(NewGroup);
db.SaveChanges();
return PartialView("_AddGroups", db.Groups);
}
I loaded up fiddler and clicked on the button but no request was being sent. Why isn't that javascript/ajax code running?
I think you need a submit button. try:
<input type="submit" value="Add Group" />
Also i think you will need to add a reference to as it doesn't look like it is included anywhere:
jquery.unobtrusive-ajax.js
I think you can get it through nuget if you dont have it already.
otherwise here is a script tag that includes a CDN link:
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.js"></script>
#foreach (var item in Model.AllManagementActions)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Id)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
I want to pass all these values to my controller. The ID , the name, etc.
Can't i just pass the item itself?
This is my current code, but it doesn't work.
<a class="complete" title="My Action" data-url="#Url.Action("Submit", "Period", new { tpId = Model.Id ,it = item})" style="cursor: pointer;">
It works if I pass item.name, item.id,item.number,etc
Can i pass the model ?
Don't iterate in your views - use editor templates for the type.
Have a '~/shared/EditorTemplates/ManagementAction.ascx' (or .cshtml if using razor) that renders a single ManagementAction.
In the view, instead of iterating use:
#Html.EditorFor(model => model.AllManagementActions)
yes you can pass the entire model, but you should use a submit button instead of of an anchor tag and also put your code inside a
using(Html.BeginForm)
{
#foreach (var item in Model.AllManagementActions)
{
//your desire.
}
<input type="submit" value="Save" />
}
in your controller you will recieve the model on post
[HttpPost]
public ActionResult SaveViewData(YourModel model)
{
//your logic.
}