MVC Ajax Beginform doesn't perform client model validation - c#

I would really appreciate any help on this issue.
Trying to create a simple Ajax Form in MVC with clientside validation.
Here's what I've done so far.
#using (Ajax.BeginForm("CreateAsync", "Page", new AjaxOptions() { HttpMethod = "POST" , OnComplete= "", OnSuccess= "P3Functions.onCreateSuccess()" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.Partial("~/Views/Shared/Partial/_createPageCore.cshtml", Model)
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
<input type="button" value="Close" class="btn btn-default" onclick="P3Functions.closeCreate()" />
</div>
</div>
</div>
}
It's a form that loads a partial view with the form content. (I've also tried to insert the code directly into the page. No difference)
This form gets loaded into a div using Ajax.ActionLink.
<div class="pageItem_control">
#Ajax.ActionLink("Add New Page", "PartialCreate", new { controller = "Page" },
new AjaxOptions
{
UpdateTargetId = "createFormDivId",
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET"
},
new { #class = "btn btn-default", #onclick = "P3Functions.displayCreate()" })
</div>
Other configurations:
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
Bundle config
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate.js", "~/Scripts/jquery.validate.unobtrusive.min.js"));
_Layout.cshtml
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#Scripts.Render("~/bundles/CustomScript")
#Scripts.Render("~/bundles/jqueryval")
PageModel.cs
[Required(ErrorMessage ="Title is required")]
public string DisplayTitle { get; set; }
_createPageCore.cshtml
<h4>Create New Page</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.DisplayTitle, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DisplayTitle, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.DisplayTitle, "", new { #class = "text-danger" })
</div>
</div>
At the moment it directly goes to the server without any client side validation. However on serverside ModelState is not valid.
Any thoughts or help will be greatly appreciated.

For anyone having the same issue:
Chuck in
<script type="text/javascript">
jQuery.validator.unobtrusive.parse();
jQuery.validator.unobtrusive.parse("#formId");
</script>
Where you're loading form content. This parses the newly added DOM fields.

Related

Add content of ajax form to div ASP.NET MVC

I have this ajax form:
#using (#Ajax.BeginForm("Create", "Comment", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "comments", InsertionMode = InsertionMode.InsertBefore }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.TextAreaFor(model => model.Content, new{#class = "form-control", id = "exampleFormControlTextarea1", rows = "5", width = "100%", placeholder = "Enter a comment here..." })
#Html.ValidationMessageFor(model => model.Content, "", new { #class = "text-danger" })
</div>
<div class="form-group">
<div class="col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
And want to add the whole content after it gets posted to this div:
<div class="comments"></div>
After searching a bit, I know it should be doable with UpdateTargetId and InsertionMode, but I still don't get it. Any help would be appreciated!

Does Ajax.BeginForm Support File Uploading?

I use HttpPostedFileBase as model for the file, but the files comes
Null to the controller, I want to use the AjaxForm tha Asp.net provides not the regular BeginForm i need to post this throw ajax ?
#using (Ajax.BeginForm("UploadImg", "Controller", Object,
new AjaxOptions { HttpMethod ="Post", OnComplete = "Something();" },
new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="col-lg-7">
#Html.TextBoxFor(model => model.File, new { type = "file", #class = "form-control", required = "required" })
<input type="submit" value="Upload" class="btn-primary" />
</div>
</div>
</div>
}

c# MVC code for the Editing Button, but clicking on the Edit button does not post it

I use the following code for the Editing Button, but clicking on the Edit button does not post it
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "PageID,GroupID,Title,ShortDescription,Text,Autor,Tags,Visit,ImageName,ShowInSlider,CreatDateTime")] Page page,HttpPostedFileBase imgUp)
{
if (ModelState.IsValid)
{
if (imgUp != null)
{
if (page.ImageName != null)
{
System.IO.File.Delete(Server.MapPath("/PageImages/" + page.ImageName));
}
page.ImageName = Guid.NewGuid() + Path.GetExtension(imgUp.FileName);
imgUp.SaveAs(Server.MapPath("/PageImages/" + page.ImageName));
}
pageRepository.UpdatePage(page);
pageRepository.save();
return RedirectToAction("Index");
}
....
I have separate data layer and repository and I use the following code for the Editing Pages Controller, but with clicking on the Edit button does not post form. Though it works well for creation and delete btn. my view code is:
<div class="form-horizontal">
<h4>Page</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.PageID)
#Html.HiddenFor(model => model.Visit)
#Html.HiddenFor(model => model.CreatDateTime)
#Html.HiddenFor(model => model.ImageName)
<div class="form-group">
#Html.LabelFor(model => model.GroupID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("GroupID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.GroupID, "", new { #class = "text-danger" })
</div>
</div>
....
<div class="form-group">
#Html.LabelFor(model => model.ImageName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="imgUp" id="imgUp"/>
#Html.ValidationMessageFor(model => model.ImageName, "", new { #class = "text-danger" })
#if (Model.ImageName != null)
{
<img src="/PageImages/#Model.ImageName" class="thumbnail" style="max-width:150px" />
}
.....
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
i trace my code and find this eror:
Application Insights Telemetry (unconfigured): {"name":"Microsoft.ApplicationInsights.Dev.Request","time":"2018-04-25T08:10:44.3663705Z","tags":{"ai.internal.sdkVersion":"web: 2.0.0.25000","ai.device.roleInstance":"Laptop-erfan","ai.operation.name":"GET PageGroup
above horizontal form tag is this code:
#model DataLayer.Page
#{
ViewBag.Title = "Edit";}<h2>Edit</h2>#using (Html.BeginForm("Edit", "Pages", FormMethod.Post, new { enctype = "multipart/form-data" })){ #Html.AntiForgeryToken()
As mentioned in the comments it doesn't look like you have a form in your view. You can add one using:
#using (Html.BeginForm()) {
<!-- form contentshere -->
}
BeingForm has several overloads as well that you can use to change where it goes to, form method (GET/PUT) and set html attributes.
You need to add the complete form page into a Form tag.
please Use
#using (Html.BeginForm()) {
//Put your complete code inside this form...
}
It will create the Form tag with specified actions and type.
You can also specific the custom action method and type of the method as well.

Get Input of second form in MVC page

I've built a page, where master and details(pictures, aso) are shown on one page. However, if the submitt button for the second form is clicked, the form is not submitted, if validations in the first form fail. If I correct the values, the HttpPostedFileBase uploadFile is null.
The page looks like this:
#model app1.Models.MasterModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm(new { #class = "form-inline col-lg-12" }))
{
#Html.AntiForgeryToken()
<div>
<h4>MasterModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
<div class="row">
#*Master properties*#
<div class="col-md-4 col-lg-4">
<div class="form-horizontal">
<div class="form-group">
#Html.LabelFor(model => model.Title, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-8">
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Title, "", new { #class = "text-danger" })
</div>
</div>
#* aso... *#
</div>
</div>
}
#* Master Details *#
<div class="col-md-4 col-lg-4">
#using (Html.BeginForm("NewPic", "Master", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input name="uploadFile" type="file" />
<input type="submit" value="Upload File" /> <!-- First Button, does not work -->
<div class="container-fluid">
#foreach (app1.Models.PicModel b in Model.Pics)
{
var base64 = Convert.ToBase64String(b.DbPic);
var imgSrc = String.Format("data:image/gif;base64,{0}", base64);
<img src="#imgSrc" width="200" height="200" />
}
</div>
#Html.ActionLink("Upload", "NewPic", new { id = Model.Id }) <!-- Second Button, does not work either -->
<label class="control-label col-md-4 col-lg-4" for="Title">Picer</label>
}
</div>
</div>
<div>
<div class="form-group">
<div class="col-md-offset-2 col-md-12 col-lg-12">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
The controller looks like this:
public ActionResult NewPic(int id, HttpPostedFileBase uploadFile)
{
// uploadFile is null
}
You forgotten to put [HttpPost] before NewPic method. So NewPic method will be considered as [HttpGet] so it will not work.
[HttpPost]
public ActionResult NewPic(int id, HttpPostedFileBase uploadFile)
{
// uploadFile is null
}
And also give proper Id to both form as follow so it would be easy to work with this both while client side validation.
Form 1
#using (Html.BeginForm(new {id = "Form1", #class = "form-inline col-lg-12" }))
Form 2
#using (Html.BeginForm("NewPic", "Master", FormMethod.Post, new { id = "Form2", enctype = "multipart/form-data" }))
For more information visit here

Multiple submit buttons from multiple views ASP .NET MVC5

I´m working on ASP .NET MVC 5 application and now I´m implementing newsletter functionality. I have master (parent view) with all stuff and on this view there is also box with input field for email and submit button. After click on this button, controller method insert this e-mail to subscribers tab. I´ve got GET/POST method and PartialView for this Newsletter (all newsletter´s code is in separate area).
Everything works fine, there is only one problem. On master page I have another submit button (for submitting search string) so everytime after submitting search string, code also submit newsletter form.
Is there any solution to separate this two submit buttons and way to not refresh whole page after submit newsletter (PartialView) form?
Here is my Newsletter PartialView called _SignIn
#using (Html.BeginForm())
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.email, htmlAttributes: new {#class = "control-label col-md-12", style="text-align: left; padding-left: 30px;"})
<div class="col-md-12" align="center">
#Html.EditorFor(model => model.email, new {htmlAttributes = new {#class = "form-control"}})
#Html.ValidationMessageFor(model => model.email, "", new {#class = "text-danger"})
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.NewsletterType, htmlAttributes: new { #class = "control-label col-md-12", style = "text-align: left; padding-left: 30px;" })
<br />
<div class="col-md-12" align="center">
#Html.EnumDropDownListFor(model => model.NewsletterType, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.NewsletterType, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-4 col-md-10" style="padding-bottom: 10px;">
<input type="submit" value="Prihlásiť" class="btn btn-success" />
</div>
</div>
</div>
Thank you for any response!
You will only achieve this using ajax calls, with that, you do not need to refresh the whole page.
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.email, htmlAttributes: new {#class = "control-label col-md-12", style="text-align: left; padding-left: 30px;"})
<div class="col-md-12" align="center">
#Html.EditorFor(model => model.email, new {htmlAttributes = new {#class = "form-control", id = "emailTxt"}})
#Html.ValidationMessageFor(model => model.email, "", new {#class = "text-danger"})
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.NewsletterType, htmlAttributes: new { #class = "control-label col-md-12", style = "text-align: left; padding-left: 30px;" })
<br />
<div class="col-md-12" align="center">
#Html.EnumDropDownListFor(model => model.NewsletterType, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.NewsletterType, "", new { #class = "text-danger", id = "ddlType" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-4 col-md-10" style="padding-bottom: 10px;">
<button type="button" class="btn btn-success btn-newsletter"></button>
</div>
</div>
</div>
<script>
$(function(){
var model = {
email: $('.emailTxt').text();
NewsletterType: $('.ddlType :selected').text();
}
$(.btn-newsletter).click(function(){
$.ajax({
url: url,
type: 'POST',
data: model,
beforeSend: function(xhr){xhr.setRequestHeader('__RequestVerificationToken', $('body').find('input[name="__RequestVerificationToken"]'));},
statusCode: {
200: function (data) { success(data); },
500: function (erro) { error(erro); }
}
});
});
});
</script>
Add name attribute to your buttons, and use the value in your controller to distinguish which button was invoked.
<button type="submit" id="btnSave" name="Command" value="Save">Save</button>
<button type="submit" id="btnSubmit" name="Command" value="Submit">Submit</button>
public ActionResult YourAction(Model model, string Command)
{
if(Command == "Save") {}
}
Refer to Handling multiple submit buttons for more info.
To prevent the full postback (refresh) you could use AJAX
You have to have two separate forms to handle each submission or handle it through some form of Javascript. I'd suggest using 2 separate forms. Put the search string submission in the parent view since it should be on all the pages and close the form. Then you can render your partial view for the newsletter subscription with a form inside of it.
Basically:
Parent view
...
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
...
<!-- Search string input field and submit button -->
...
</div>
}
<div>
#Html.RenderPartial("_SignUp")
</div>
...
_SignUp Partial view
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
...
<!-- Subscriber email input and submit -->
...
</div>
}

Categories

Resources