is it possible to load the modelstate errors to the same modal dialog after submitting a form with javascript?
My code is something like this:
Controller:
public ActionResult Create(MyModel model){
if(ModelState.isValid){
// DB Save
return RedirectToAction("Index");
}
else{
return View(model);
}
}
Ajax Method
$.ajax({
type: 'POST',
url: '/Receipt/Create',
cache: false,
data: $("#CreateForm").serialize(),
success: function (e) { window.location="/Controller/Action"; },
error: function (e) { e.preventDefault(); /*Code here to load model error into page*/ }
});
I've solved today this problem, with something like this
public ActionResult Create(MyModel model){
if(ModelState.isValid){
// DB Save
return RedirectToAction("Index");
}
else{
return PartialView("_myPartialForm",model);
}
}
and
$.ajax({
type: 'POST',
url: '/Receipt/Create',
cache: false,
data: $("#CreateForm").serialize(),
success: function (e) {
if(e.Valid){
window.location="/Controller/Action";}
else{
return false;
} },
error: function (e) { e.preventDefault();$("#mymodal").load(e) }
});
it is something like jmrnet said. Thanks
I was able to accomplish this by using Ajax.BeginForm method with an UpdateTargetId AjaxOption. Here is the code I used. It doesnt exactly fit what you are doing, but it should point you in the right direction.
In the View:
#using (Ajax.BeginForm(new AjaxOptions(){ UpdateTargetId="loginresult" }))
{
<b>User:</b><br />
#Html.TextBoxFor(m => m.UserName)<br />
<br />
<b>Password:</b><br />
#Html.PasswordFor(m => m.Password)<br />
<div id="loginresult"><br /></div>
<input id="Button1" type="submit" value="Login" class="touch-button" />
}
In the Controller:
[HttpPost]
public ActionResult Index(LoginModel model)
{
//Execute Log-in code.
//Capture any errors and put them in the model.LoginResponse property.
return PartialView("LoginResult", model);
}
In the LoginResult partial view:
#model MerchantMobile.Models.LoginModel
#if (String.IsNullOrEmpty(Model.LoginResponse))
{
Html.RenderPartial("_AjaxRedirect", Url.Content("~/Home/Activity"));
}
else
{
<div id="loginresult">
<div style="color: Red; font-weight: bold;">
#Model.LoginResponse
</div>
</div>
}
You could easily replace the loginresult <div> with one used by jquery ui to pop up a modal dialog box rather than just show some text in the div.
Hope this helps!
Related
I have a pop form AddorEdit.cshtml, which is called from index.cshtml page. The form is opening but unable to post data to controller method.
index page
// index.cshtml //
<a class="btn btn-success" style="margin-bottom:10px;" onclick="PopupForm('#Url.Action("AddorEdit", "Vehicles")')"><i class="fa fa-plus"></i> Add New</a>
<table id="tbl_vehicle" class="table table-striped table-bordered" style="width:100%;" >
//table block
<script>
function SubmitForm(form) {
$.ajax({
type: "POST",
url: form.action,
data: $(form).serialize(),
success: function (date) {
if(data.success)
{
Popup.dialog('close');
dataTable.ajax.reload();
}
}
});
</script>
pop up form
//AddorEdit.cshtml //
#using (Html.BeginForm("AddorEdit", "Vehicles", FormMethod.Post, new { onsubmit = "return SubmitForm(this)" }))
//form
controller method
// VehiclesController.cs //
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddorEdit([Bind(Include = "Id,VehicleType,Amount,RenewPeriod,Status")] Vehicle vehicle)
{
if (ModelState.IsValid)
{
if (vehicle.Id <= 0)
{
vehicle.RegisteredDate = DateTime.Now;
vehicle.RegisteredBy = "admin";
db.Vehicle.Add(vehicle);
}
else
{
db.Entry(vehicle).State = EntityState.Modified;
}
db.SaveChanges();
}
return Json(new { success = true, message = "Saved Successfully" }, JsonRequestBehavior.AllowGet);
}
I am unable to detect why the data is not posting to the controller method. Thank You!!!
use like this in your Form,it will fix your problem
#using (Html.BeginForm("AddorEdit", "Vehicles", FormMethod.Post, new { onsubmit =
"return SubmitForm(this)" }))
{
#Html.AntiForgeryToken()
}
if you are using
[ValidateAntiForgeryToken]
this attribute on top of your action method
you must use
#Html.AntiForgeryToken()
in your view
i'm trying to upload image using .net core with mvc ajax
here is my code
<form asp-action="AddImages" asp-controller="UserAdmin"
data-ajax-begin="onBeginSubmit" data-ajax-complete="onComplete"
data-ajax-failure="onFailed" data-ajax-success="onSuccessSubmit"
data-ajax="true" data-ajax-method="POST" enctype="multipart/form-data">
<input id="file-input-1" name="Image" type="file" class="uploadimg" data-id="1" accept=".jpg, .jpeg, .png" />
<div class="col-xs-12">
<button type="submit">Save</button>
</div>
</form>
Here is my Model
public class ImageModel
{
[Required(ErrorMessage = "Please Select Image of Product")]
public List<IFormFile> Image { get; set; }
}
And my method
[HttpPost]
public bool AddImages(ImageModel Image)
{
if (!ModelState.IsValid)
{
return false;
}
return true;
}
but Image is null and model always return false
I've just come up against this problem myself, and it seems the only way around it is to use "traditional" ajax to post the form back to the controller. My method was as follows:-
Replace the Submit button with a normal button that calls the Ajax:
<input type="button" class="btn btn-default" value="Save" onclick="javascript:submitForm()" />
Then use Ajax to gather the form data and post it back to the controller action:
function submitForm() {
var formdata = new FormData($('#yourFormId').get(0));
$.ajax({
url: '#Url.Action("YourActionName", "YourControllerName")',
type: 'POST',
data: formdata,
processData: false,
contentType: false,
success: function (data) {
//rendering success
},
error: function (xhr, ajaxOptions, thrownError) {
//rendering errors
}
});
}
Hope this helps somebody out. Shame the new "data-ajax" form tags don't seem to be able to handle posting files back.
I have created a table which dynamically generates records using the "Infinite Loading" process, I have a button in my HTML Code which i need to use to allow users to add the item in their favourite - so this is my HTML code
#model List<PagesAuth.Models.Links.MLink>
#foreach (var I in Model)
{
<tr>
<td class="v-align-top" id="itemcard">
<h4 class="card-title">
#I._title
<small><cite>#I._tp_created.ToString("dd MMM yyyy")</cite> /small>
</h4>
<div class="pull-right" id="options">
<ul class="list-inline text-right" >
#if (I._tp_favourite == 0)
{
<li><button class="btn-link glyphicon glyphicon-heart-empty" onclick="location.href='#Url.RequestContext .Action("_Fav", "Home", "#I._id")'"></button></li>
}
else
{
<li><button class="btn-link glyphicon glyphicon-heart-empty" onclick="location.href='#Url.RequestContext .Action("_UnFav", "Home", "#I._id")'"></button></li>
}
</ul>
</div>
</div>
</td>
</tr>
}
I am trying to use "Favourite" button to allow user to add that website to their favourite list (I am ok with the DB updates etc)
<ul class="list-inline text-right" >
#if (I._tp_favourite == 0)
{
<li><button class="btn-link glyphicon glyphicon-heart-empty" onclick="location.href='#Url.RequestContext .Action("_Fav", "Home", "#I._id")'"></button></li>
}
else
{
<li><button class="btn-link glyphicon glyphicon-heart-empty" onclick="location.href='#Url.RequestContext .Action("_UnFav", "Home", "#I._id")'"></button></li>
}
</ul>
What I want to know is how to achieve this on user front-end - Like I thought I should just create a PartialView and make it child action only in my controller, send it ID and do DB Processing
[ChildActionOnly]
public ActionResult _Fav(int ID)
{//Do DB Processing
return PartialView(ID);
}
First of all the following does not work
onclick="location.href='#Url.RequestContext .Action("_UnFav", "Home", "#I._id")'"
Second, if I end up making this work, it will still refresh the page and I don't want that.
Is there a better way to achieve this
Cheers
I don't know why you want to use partial views but you can do it this way.
Use ajax to send request to controller action.
Handle action result using JavaScript.
View:
#model List<PagesAuth.Models.Links.MLink>
#foreach (var I in Model)
{
<tr>
<td class="v-align-top" id="itemcard">
<h4 class="card-title">
#I._title
<small><cite>#I._tp_created.ToString("dd MMM yyyy")</cite> /small>
</h4>
<div class="pull-right" id="options">
<ul class="list-inline text-right" >
#if (I._tp_favourite == 0)
{
<li><button class="btn-link glyphicon glyphicon-heart-empty" onclick="Fav(#I._id)"></button></li>
}
else
{
<li><button class="btn-link glyphicon glyphicon-heart-empty" onclick="UnFav(#I._id)"></button></li>
}
</ul>
</div>
</div>
</td>
</tr>
}
JS:
Here I am just alerting that the favorite action succeeded, else you have an array of string errors to work with. You could redirect or do some stuff, whichever you prefer.
<script type="text/javascript">
function Fav(id) {
var url = '#Url.Action("_Fav", "Home")';
$.ajax({
url: url,
type: 'POST',
data: {
id: id
},
success: function (data) {
if(data.length == 0) // No errors
alert("Fave success!");
},
error: function (jqXHR) { // Http Status is not 200
},
complete: function (jqXHR, status) { // Whether success or error it enters here
}
});
};
function UnFav(id) {
var url = '#Url.Action("_UnFav", "Home")';
$.ajax({
url: url,
type: 'POST',
data: {
id: id
},
success: function (data) {
if(data.length == 0) // No errors
alert("Unfave success!");
},
error: function (jqXHR) { // Http Status is not 200
},
complete: function (jqXHR, status) { // Whether success or error it enters here
}
});
};
</script>
Controller:
[HttpPost]
public ActionResult _Fav(int ID)
{
List<string> errors = new List<string>(); // You might want to return an error if something wrong happened
//Do DB Processing
return Json(errors, JsonRequestBehavior.AllowGet);
}
[HttpPost]
public ActionResult _UnFav(int ID)
{
List<string> errors = new List<string>(); // You might want to return an error if something wrong happened
//Do DB Processing
return Json(errors, JsonRequestBehavior.AllowGet);
}
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");
}
});
});
});
I've got a really strange problem where my ajax post request works fine the first time after the page has loaded but if I submit my form again without doing a page refresh then the contents are returned to the whole page instead of just updating the DIV. I've spent days on this looking for answers and through trial and error and I suspect the issue relates to Request.Headers["X-Requested-With"] being empty on 2nd submit. Note that I am returning a View Component to the ajax request and my ajax code is in a separate js file.
View Component (this contains the form that gets submitted and gets replaced when the ajax request returns. It works correctly after the page has been loaded or refreshed)
#model MSIC.Models.ClientViewModels.VisitMovementViewModel
#{
bool inProgress = (bool)ViewData["inProgress"];
}
<form asp-controller="Client" asp-action="VisitMovement" asp-route-id="#Model.VisitMovementID" id="formVisitAction" method="post" onsubmit="AjaxSubmit(this)">
<input asp-for="VisitID" type="hidden" />
<input asp-for="StageNo" type="hidden" />
<input type="hidden" id="replaceID" name="replaceID" value="#ClientVisit" />
<input type="hidden" id="submitAction" name="submitAction" />
<div class="col-md-9 no-padding">
<input type="text" id="visitMovementComment" name="visitMovementComment" class="form-control" placeholder="Comment..." required>
</div>
<div class="input-group col-md-3">
<input type="text" id="visitMovementBoothNo" name="visitMovementBoothNo" class="form-control" placeholder="Booth..." required>
<div class="input-group-btn">
<button type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" #((inProgress) ? "" : "disabled")>Action <span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-right">
#if (Model.Buttons != null)
{
foreach (var item in Model.Buttons)
{
if (item.beforeDivider)
{
<li><button type="#item.Type" name="#item.Name" class="btn btn-link btn-block btn-flat" value="#item.Value" onclick="#item.OnClick">#item.Text</button></li>
}
}
<li role="separator" class="divider"></li>
foreach (var item in Model.Buttons)
{
if (!item.beforeDivider)
{
<li><button type="#item.Type" name="#item.Name" class="btn btn-link btn-block btn-flat" value="#item.Value" onclick="#item.OnClick">#item.Text</button></li>
}
}
}
</ul>
</div>
</div>
</form>
Ajax Request located in separate JS file (when debugging this everything runs through as expected the first time however after the View Component is returned and the form is submitted the 2nd time the success, error, complete functions never fire and the returned data loads in the whole page)
function AjaxSubmit(form) {
$form = $(form);
var replaceID = $('input#replaceID', $form).val();
var formData = $form.serialize();
if (!$form[0].checkValidity()) {
return false;
}
$form.submit(function (e) {
e.preventDefault();
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: formData,
async: true,
processData: false,
cache: false,
success: function (data) {
$(replaceID).html(data);
},
error: function (xhr, status, error) {
console.log(xhr.status + " - " + error);
},
complete: function (data) {
console.log(data);
}
});
});
}
Action Method (I suspect the issue may be related to the Request.Headers["X-Requested-With"] being Empty on the 2nd submit and therefore MVC does not realise this is an ajax request hence returns the result to the page instead of returning it to the ajax request)
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> VisitMovement(int id, int submitAction, int? visitMovementBoothNo, string visitMovementComment, VisitMovementViewModel model)
{
var test1 = Request.ContentType; //1ST REQUEST = "application/x-www-form-urlencoded; charset=UTF-8", 2ND REQUEST = "application/x-www-form-urlencoded"
var test2 = Request.Headers["X-Requested-With"]; //1ST REQUEST = "XMLHttpRequest", 2ND REQUEST = Empty
try
{
if (ModelState.IsValid)
{
bool complete = false;
switch (submitAction)
{
case 2: //Proceed to Stage 2
model.StageNo = 2;
break;
case 3: //Proceed to Stage 3
model.StageNo = 3;
break;
case 4: //Complete Visit
complete = true;
break;
default:
return BadRequest("Could not determine action.");
}
await visitAPI.VisitMovement(id, model.VisitID, submitAction, model.StageNo, visitMovementBoothNo, visitMovementComment, complete);
return ViewComponent("ClientVisit", new { visitID = model.VisitID });
}
else
{
return BadRequest(ModelState);
}
}
catch (Exception ex)
{
return StatusCode(500, ex.Message);
}
}
If my assumption is correct why is the ajax request not sending the the correct headers when it is submitted the 2nd time and how can i fix it? If not what else could be going wrong?
I think the problem was the form submit event was being lost when the data/view component returned. I solved the problem by changing my ajax post to below...
$(document).on('submit', 'form.ajax-form', function (e) {
var replaceID = $('input#replaceID', $(this)).val();
var replaceType = $('input#replaceType', $(this)).val();
e.preventDefault();
$.ajax({
url: $(this).attr('action'),
type: $(this).attr('method'),
data: $(this).serialize(),
async: true,
processData: false,
cache: false,
success: function (data) {
$(replaceID).html(data);
},
error: function (xhr, status, error) {
AjaxOnFailure(xhr, status, error);
}
});
});