I Have a problem with PartialView, after call some action, the return view render out of view, like another view..
HTML PartialView
<form asp-action="SendFoo" asp-controller="Foo" method="post" enctype="multipart/form-data">
<input type="file" name="files" />
<input type="file" name="files" />
<button type="submit">Send Foo</button>
</form>
API
[HttpPost]
public async Task<IActionResult> SendFoo(IList<IFormFile> files)
{
//do something
return PartialView("_FooSendData");
}
Layout
<div class="container-fluid">
<div id="partialViewContainer">
#{Html.RenderPartial("_FooSendData"); }
</div>
</div>
but el Partial View look like this
So. How the partial view call post action, wait response, and show response in the same view...
You need to post use Ajax or javascript and update PartialView:
$('#MySubmitButtonId').live('click', function (event) {
$.post(
'#Url.Action("PostAction", "Post")',
{ content: 'GetpostDetails' },
function(result) {
$('#MyPartialContainerId').html(result);
}
);
});
For upload the file:
$(document).ready(function () {
$("#Upload").click(function () {
var formData = new FormData();
var totalFiles = document.getElementById("FileUpload").files.length;
for (var i = 0; i < totalFiles; i++)
{
var file = document.getElementById("FileUpload").files[i];
formData.append("FileUpload", file);
}
$.ajax({
type: "POST",
url: '/Controller/Action',
data: formData,
dataType: 'json',
contentType: false,
processData: false,
success: function (response) {
$('#MyPartialContainerId').html(response);
},
error: function (er) {
alert("er");
}
});
});
});
Related
I want to do a live search to filter results as I type in the textbox. There is a html Unordered list that is populated from the model when the page is loading and those are the items I want to filter when searching. Problem is how do I update the ul with the search values?
The cshtml page:
<div>
<input id="search" type="text" placeholder="Search Sections">
<ul id="menuList" style="max-height: 800px; overflow:scroll;">
#foreach (var item in Model)
{
<li>
<div style="display:inline-block; min-width:15%">#item.Index</div>
<div style="display:inline; min-width:80%">#item.Title</div>
</li>
}
</ul>
</div>
The ajax call:
$(function () {
$("#search").keyup(function (e) {
var s = $("#search").val();
$.get("/Document/GetSearchItem?searchString=" + s, function (r) {
//how do I update ui with results here?
});
});
});
The controller method that query's the db and returns a list that I use to update the model, this works well.
public async Task<IActionResult> GetSearchItem(string searchString)
{
var lst = await _sectionService.GetSearchString(searchString);
var documentModel = new List<DocumentViewModel>();
foreach (var item in lst)
{
documentModel.Add(new DocumentViewModel
{
Id = item.Id.ToString(),
Title = item.Title,
Index = item.IndexNumber
});
}
return View(documentModel);
}
In the controller:
public ActionResult Index()
{
return View();
}
public JsonResult Refresh(string search)
{
return Json(Records(search), JsonRequestBehavior.AllowGet);
}
private List<DocumentViewModel> Records(string search)
{
var list = /* your code to obtain records */;
return (String.IsNullOrEmpty(search)) ? list : list.Where(r => r.Title.StartsWith(search)).ToList();
}
The Index.cshtml:
#*
There is no data model here - the jQuery is working excellent for this example.
*#
<!DOCTYPE html>
<script>
window.onload = function () {
Refresh();
}
function Refresh() {
var search = document.getElementById("search").value;
$.ajax({
type: "GET",
url: '#Url.Action("Refresh", "Home")',
contentType: "application/json;charset=utf-8",
data: { search },
dataType: "json",
success: function (data) {
$('#menuList').empty();
for (var i = 0; i < data.length; i++) {
$('#menuList').append('<li><div style="display:inline-block; min-width:15%">'
+ data[i].Index + '</div>'
+ '<div style="display:inline; min-width:80%">' + data[i].Title + '</div></li>'
);
}
}
});
};
</script>
<html>
<body>
<div>
<input id="search" type="text" placeholder="Search Sections" onkeyup="Refresh()">
<ul id="menuList" style="max-height: 800px; overflow:scroll;">
</ul>
</div>
</body>
</html>
I was having similar kind of functioanlity in one of my asp.net projects and handled the ajax call this way. Check if it helps.
function SearchText() {
$("#search").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "samplepage.aspx/samplemethod",
data: "{'searchValue':'" + document.getElementById('#search').value + "'}",
dataType: "json",
success: function (data) {
response(data.d);
},
error: function (result) {
alert("No Match");
}
});
}
});
}
You will just have to use jQuery to do it manually.
Check this answer for some ideas: How to add items to a unordered list <ul> using jquery
You need to give the li a dynamic id
<li id="li_#item.Index">
and in filter function hide all li items under ul,
then loop the result to show selected items
I have tried looking at answers to similar questions and none of them work for my code. I have tried a lot of different things, all it should do is post the fullname and then display it back in the view.
The view code:
<script type="text/javascript">
$(document).ready(function () {<script type="text/javascript">
$(document).ready(function () {
$('#buttonDemo2').click(function () {
var fullName = $('#fullName').val();
var payload = {fn : fullName};
$.ajax({
type: 'POST',
url: '/demo/demo2/',
contentType: 'application/json',
data: JSON.stringify(payLoad),
success: function (result) {
$('#result2').html(result);
}
});
});
</script>
<fieldset>
<legend>Demo 2</legend>
Full Name <input type="text" id="fullName" />
<input type="button" value="Demo 2" id="buttonDemo2" />
<br />
<span id="result2"></span>
</fieldset>
The controller code:
[HttpPost]
public IActionResult Demo2(string fullName)
{
return new JsonResult("Hello " + fullName);
}
First, when you pass string by ajax to action,you should ensure the received parameter name is the same as the incoming parameter name.
So, you should change var payload = {fn : fullName}; to var payload = {fullName: fullName};, or change public IActionResult Demo2(string fullName) to public IActionResult Demo2(string fn).
Then, because you passed only a string not an object parameter , so you don't need to use JSON.stringify, and remove contentType: 'application/json' .
Here is the detailed code:
<script type="text/javascript">
$(document).ready(function () {
$('#buttonDemo2').click(function () {
var fullName = $('#fullName').val();
var payload = { fullName: fullName }; // change name
$.ajax({
type: 'POST',
url: '/demo/demo2/',
// contentType: 'application/json', // remove this line
data: payload, //remove JSON.stringify
success: function (result) {
$('#result2').html(result);
}
});
});
});
</script>
<fieldset>
<legend>Demo 2</legend>
Full Name <input type="text" id="fullName" />
<input type="button" value="Demo 2" id="buttonDemo2" />
<br />
<span id="result2"></span>
</fieldset>
Controller:
[HttpPost]
public IActionResult Demo2(string fullName)
{
return new JsonResult("Hello " + fullName);
}
Here is the test result:
I am programing a web application, The first page will be the login page, I already did that on the RouteConfig. I developed a function that do the checking with the controller, back with successfull message and after should reidrect to my index page. The message is shown but the redirection never passed. I tried to use two separate functions and controllers for login part and redirection part, with ng-submit for all the login form to do the login check and ng-click on the login submit to do the redirection. Please help me with that.
DataController :
public JsonResult UserLogin (LoginData d)
{
using (GestReclamationDBEntities dc = new GestReclamationDBEntities())
{
var user = dc.Users.Where(a => a.Username.Equals(d.Username) &&
a.Password.Equals(d.Password)).FirstOrDefault();
return new JsonResult { Data = user, JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
}
public ActionResult Index()
{
return View();
}
login-controller.js :
(function () {
'use strict';
angular
.module('app')
.controller('LoginController', function ($scope, $window, LoginService) {
$scope.IsLogedIn = false;
$scope.Message = '';
$scope.Submitted = false;
$scope.IsFormValid = false;
$scope.LoginData = {
Username: '',
Password: ''
};
//Check is Form Valid or Not
$scope.$watch('f1.$valid', function (newVal) {
$scope.IsFormValid = newVal;
});
$scope.login = function () {
$scope.Submitted = true;
if ($scope.IsFormValid) {
LoginService.GetUser($scope.LoginData).then(function (d) {
if (d.data.Username != null) {
var host = $window.location.host;
var landingUrl = "/Data/Index";
$scope.IsLogedIn = true;
$scope.Message = "Successfully login done. Welcome ";
$window.location.href = landingUrl;
}
else {
alert('Invalid Credential!');
}
});
}
};
})
.factory('LoginService', function ($http) {
var fac = {};
fac.GetUser = function (d) {
return $http({
url: '/Data/UserLogin',
method: 'POST',
data: JSON.stringify(d),
headers: { 'content-type': 'application/json' }
});
};
return fac;
});
})();
Login.cshtml :
<div ng-controller="LoginController">
<div class="login-form">
<form novalidate name="f1" ng-submit="login()">
<div style="color:rgb(142,2,2)">{{Message}}</div>
<div ng-show="!IsLogedIn">
<h2 class="text-center">Log in</h2>
<div class="form-group">
<input type="text" class="form-control" placeholder="Username" ng-
model="LoginData.Username" name="cUsername" ng-class="Submitted?'ng-dirty':''" required autofocus>
<span class="error" ng-show="(f1.cUsername.$dirty || Submitted) &&
f1.cUsername.$error.required">Username required</span>
</div>
<div class="form-group">
<input type="password" class="form-control" placeholder="Password" ng-
model="LoginData.Password" name="cPassword" ng-class="Submitted?'ng-dirty':''" required autofocus>
<span class="error" ng-show="(f1.cPassword.$dirty || Submitted) &&
f1.cPassword.$error.required">Password required</span>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">Log in</button>
</div>
</div>
</form>
</div>
</div>
#section scripts{
<script src="~/Scripts/app/controllers/login-controller.js"></script>
#*<script src="~/Scripts/app/controllers/access-to-app-controller.js"></script>*#
}
EDIT :
I tried to work with location.href like this :
$("#send").click(function () {
$.ajax({
type: 'POST',
url: '#Url.Action("Login")',
//dataType: 'json',
//contentType: dataType,
data: { Username: $("#Username").val(), Password:
$("#Password").val() },
success: function (result) {
if (true) {
location.href = '/Data/Index';
} else {
location.href = 'Login';
}
},
error: function (result) {
}
});
});
I also add the id="send" to my Login button. Now when I click on login he goes directly yo the index page without verifiying credentials.
Try to do a location.href ='Controller/Method';
Do something like that
$.ajax({
type: 'POST',
url: '#Url.Action("Login")',
//dataType: 'json',
//contentType: dataType,
data: { Username: $("#Username").val(), Password: $("#Password").val() },
success: function (result) {
if (//anything in result) {
location.href = 'Controller1/Index1';
} else {
location.href = 'Controller2/Index2';
}
},
error: function (result) {
}
});
I'm struggling to get a file to upload. I've checked a dozen samples here (copied code verbatim) and nothing works. I get no errors, no upload, I just get nothing.
I set a breakpoint in my controller but it doesn't get hit. All my code is below, what am I doing wrong
I'm using asp.net.core 2.2 and VS2019
HTML
<div class="card">
<div class="card-header">
<div class="row">
<div class="col">
<h4>Import Users</h4>
</div>
<div class="col">
<form id="frmUpload" action="#Url.Action("PerformImportUsers","Admin")" method="post">
#Html.AntiForgeryToken()
<div class="input-group">
<div class="custom-file">
<input type="file" class="custom-file-input" name="importFile" id="inputGroupFile02">
<label class="custom-file-label" for="inputGroupFile02" style="overflow:hidden;">Choose file</label>
</div>
<div class="input-group-append">
<span class="fa fa-upload"></span>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
JS
<script>
$("#uploadFile").on("click", function (e) {
e.preventDefault();
//e.stopPropagation();
debugger;
var myForm = $("#frmUpload");
var sUrl = myForm.attr("action");
var files = $("#inputGroupFile02").get(0);
var formData = new FormData();
for (var i = 0; i != files.length; i++) {
formData.append("myfile", files[i]);
}
$.ajax({
type: "POST",
url: sUrl,
contentType: false,
processData: false,
data: formData,
success: function (result) {
var data = jQuery.parseJSON(result);
showNotify(data.message);
},
error: function () {
alert("there was an error");
}
});
});
</script>
CONTROLLER
[HttpPost]
//[ValidateAntiForgeryToken]
public JsonResult PerformImportUsers(List<IFormFile> importFile)
{
return new JsonResult(new { result = "success", message = "Uploaded" });
}
To upload a file your form tag needs enctype="multipart/form-data"
Try adding that and you should see the file come through in the back end.
And remove that javascript, that is not needed.
[HttpPost]
//[ValidateAntiForgeryToken]
public JsonResult PerformImportUsers() // remove parameter
{
var files = this.Request.Form.Files; //retreive files
return new JsonResult(new { result = "success", message = "Uploaded" });
}
Besides this code below will only add 1 file
for (var i = 0; i != files.length; i++) {
formData.append("myfile", files[i]); // change it to "myfile"+i
}
First of all, press F12 in browser to check the action (sUrl) is correct or not,it should be action="/Admin/PerformImportUsers".
Then change your js to below to upload files using formdata.You need to match name of formData to the parameter name (importFile)on POST method.
<script>
$("#uploadFile").on("click", function (e) {
e.preventDefault();
var myForm = $("#frmUpload");
var sUrl = myForm.attr("action");
var input = document.getElementById("inputGroupFile02");
var files = input.files;
var formData = new FormData();
for (var i = 0; i != files.length; i++) {
formData.append("importFile", files[i]);
}
$.ajax({
type: "POST",
url: sUrl,
contentType: false,
processData: false,
data: formData,
success: function (result) {
var data = jQuery.parseJSON(result);
showNotify(data.message);
},
error: function () {
alert("there was an error");
}
});
});
</script>
I am very new to both JQuery and Asp.net MVC 3 (C#), so I apologize if this is trivial. I have an MVC partial view (Index.cshtml) that has a list of tasks. These tasks are contained within indivudal divs that I have in a list style layout. I have a button called "add task" that opens a dialog. This dialog will save the added task to the database via an AJAX Json call to the controller.
This is where I am having trouble - after the dialog closes I would like the list of tasks to reload with the task i just added. I have found examples where the entire page is reloaded, and I found examples where the controller is supposed to return a rendered view. My problem is that the dialog is being opened from the partial I want to reload. Is there a way to accomplish what I am trying to do.
Index.cshtml
#model IEnumerable<TaskManagementApplication.Models.Project>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div id="ProjectAccordionWrapper">
#foreach (var item in Model)
{
<div class="ProjectWrapper">
<h3>#item.Name</h3>
<div class="column">
<button class="createTaskButton" id="#item.ProjectID">Create New Task</button>
#foreach(var task in item.Tasks) {
var buttonClass = "taskID" + task.TaskID;
<div class="portlet">
<div class="portlet-header">#task.TaskName</div>
<div class="portlet-content">#task.TaskDescription</div>
<button class="editTaskButton" id="#task.TaskID">Edit Task</button>
</div>
}
</div>
</div>
}
</div>
<div id="dialog-form" title="Create new user">
<p class="validateTips">All form fields are required.</p>
<form>
<fieldset>
<label for="TaskName">Task Name</label>
<input type="text" name="TaskName" id="name" class="text ui-widget-content ui-corner-all" />
<label for="TaskDescription">Task Description</label>
<input type="text" name="TaskDescription" id="description" value="" class="text ui-widget-content ui-corner-all" />
<input type="hidden" name="TaskID" id="ID" />
<input type="hidden" name="ProjectID" id="ProjectID" />
</fieldset>
</form>
</div>
Partial Javascript
function GetTask(id) {
if (id.length > 0) {
$.ajax({
url: '/Project/GetTaskFromID',
type: "POST",
data: { "id": id },
success: PopulateDialogFields,
error: HandleError
});
}
}
function PopulateDialogFields(data) {
$("#name").val(data.TaskName);
$("#description").val(data.TaskDescription);
$("#ID").val(data.TaskID);
}
function HandleError(data) {
alert(data.error);
var foo = data;
}
function SaveTask() {
var taskName = $("#name").val();
var taskDescription = $("#description").val();
var id = $("#ID").val();
var projectID = $("#ProjectID").val();
if (id.length > 0) {
$.ajax({
url: '/Project/SaveTask',
type: "POST",
data: { "taskName": taskName, "taskDescription": taskDescription, "taskID": id }
});
}
else {
$.ajax({
url: '/Project/SaveTask',
type: "POST",
data: { "taskName": taskName, "taskDescription": taskDescription, "projectID": projectID }
});
}
}
$("#dialog-form").dialog({
autoOpen: false,
height: 300,
width: 350,
modal: true,
buttons: {
"OK": function () {
SaveTask();
$(this).dialog("close");
},
Cancel: function () {
$(this).dialog("close");
}
},
close: function () {
allFields.val("").removeClass("ui-state-error");
window.location.reload(true);
},
open: function () {
var id = $(this).data("id");
var projectID = $(this).data("projectID");
$("#ProjectID").val(projectID);
var button = $("#" + id);
GetTask(id);
}
});
$(".editTaskButton")
.button()
.click(function () {
$("#dialog-form").data('id', this.id).dialog("open");
});
$(".createTaskButton")
.button()
.click(function () {
$("#dialog-form").data('projectID', this.id).dialog("open");
});
I am relatively new to jQuery and ASP.NET MVC as well, however, here's what first comes to mind.
In order to maintain the AJAX-y aspect of the page, I suggest that you create a method that handles a POST which returns a JSON formatted set of TaskManagementApplication.Models.Project. This method can optionally return filtered results.
The markup would look like this,
<div id="ProjectAccordionWrapper">
<div id="ProjectWrapperTemplate" class="ProjectWrapper" style="display: none;">
<h3 id="itemName"></h3>
<div class="column">
<button class="createTaskButton" id="itemProjectID">Create New Task</button>
<div id="portletTemplate" class="portlet">
<div class="portlet-header" id="taskName"></div>
<div class="portlet-content" id="taskDescription"></div>
<button class="editTaskButton" id="taskID">Edit Task</button>
</div>
</div>
</div>
</div>
Next, you would have jQuery clone the ProjectWrapperTemplate element, and set all of the corresponding fields.
$(function () {
$.ajax({
url: '/Project/GetTasks',
type: "POST",
data: { }
}).done(function (data) {
data.forEach(function (element) {
AppendProjectWrapper(element);
});
});
function AppendProjectWrapper(data) {
var projectAccordionWrapper = $('#ProjectAccordionWrapper');
var projectWrapper = $('#ProjectWrapperTemplate').clone(true, true);
projectWrapper.id = nothing; // remove the id, so as to not have duplicates
projectWrapper.style.display = nothing; // remove the style "display: none"
var itemName = projectWrapper.children('#itemName'); // h3
itemName.id = nothing;
itemName.text(data.ItemName);
var itemProjectID = projectWrapper.children('#itemProjectID'); // button Create New Task
itemProjectID.id = data.ItemProjectID;
var portletTemplate = projectWrapper.children('#portletTemplate'); // div
data.Tasks.forEach(function (element) {
var portlet = portletTemplate.clone();
portlet.id = nothing;
var taskName = portlet.children('#taskName');
taskName.id = nothing;
taskName.text(element.TaskName);
var taskDescription = portlet.children('#taskDescription');
taskDescription.id = nothing;
taskDescription.text(element.TaskDescription);
var editTaskButton = portlet.children('#taskID');
editTaskButton.id = element.TaskID;
portlet.appendTo(projectWrapper);
});
portletTemplate.remove(); // remove the portlet template element
projectWrapper.appendTo(projectAccordionWrapper);
}
}
Finally, have '/Project/SaveTask' return a JSON formatted TaskManagementApplication.Models.Project of the currently saved task.
$.ajax({
url: '/Project/SaveTask',
type: "POST",
data: { "taskName": taskName, "taskDescription": taskDescription, "taskID": id }
}).done(function (data) {
AppendProjectWrapper(data);
});
The return data for '/Project/GetTasks' should look as follows:
[
{
ItemName: '#item.Name',
ItemProjectID: '#item.ProjectID',
Tasks: [
TaskName: '#task.TaskName',
TaskDescription: '#task.TaskDescription',
TaskID: '#task.TaskID'
]
}
]
The return data from '/Project/SaveTask' should follow the same format, except or the outer-most array.
Please note that a lot of this code is untested.
It may be easiest to refactor the list into another action+view. Then, you can call this in both the original Index.cshtml view, and via the .load() method in jQuery. So, assuming this:
Projects controller
[HttpGet]
[ChildActionOnly]
public ActionResult Tasks(int id)
{
// create the appropriate model object as an IEnumerable of your Task type
return View(model);
}
Tasks.cshtml
#foreach(var task in Model) {
var buttonClass = "taskID" + task.TaskID;
<div class="portlet">
<div class="portlet-header">#task.TaskName</div>
<div class="portlet-content">#task.TaskDescription</div>
<button class="editTaskButton" id="#task.TaskID">Edit Task</button>
</div>
}
You would adjust Index.cshtml like so:
#model IEnumerable<TaskManagementApplication.Models.Project>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div id="ProjectAccordionWrapper">
#foreach (var item in Model)
{
<div class="ProjectWrapper">
<h3>#item.Name</h3>
<div class="column">
<button class="createTaskButton" id="#item.ProjectID">Create New Task</button>
<div id="tasks-#item.ProjectID">
#Html.Action("Tasks", "Project", new { id = item.ProjectID })
</div>
</div>
</div>
}
</div>
//... the rest of the view
And finally,
// this should happen inside the callback of your .ajax() method
$('#tasks-'+projectID).load('/project/tasks/'+ projectID);