Does Ajax.BeginForm Support File Uploading? - c#

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>
}

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!

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

Why my button is not calling action in the controller?

I have EDITSTORIES partial view which must post data to UpdateStories action in Stories controller but it doesn't. It doesn't even hit the breakpoint.
#using (Html.BeginForm("UpdateStories", "Stories", FormMethod.Post, new{enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Stories</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.Image, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Image, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Image, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Story, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Story, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Story, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Update" class="btn btn-default" />
</div>
</div>
</div>
}
Action:
[HttpPost]
public ActionResult UpdateStories(Stories st)
{
ViewBag.Grid= bo.GetAllImages();
if (bo.UpdateImages(st))
{
ViewBag.Data = "Updated successfully";
}
else
{
ViewBag.Data = "Update failed";
}
ViewBag.Style = "display:none";
return View("GetStories", st);
}
}
It's inside the GetStories which is the main view. It's been a long day and still, it hasn't been done. Please help me with it.
Update:
Routes:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Stories", action = "AddStories", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "ShowStories",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Stories", action = "ShowStories", id = UrlParameter.Optional }
);
Update:
View: GetStories
#model HimHer.Models.Stories
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (#Html.BeginForm("GetStories", "Stories", FormMethod.Get))
{
#Html.AntiForgeryToken()
<div style="#ViewBag.Style">
#{
Html.RenderPartial("EditStories", Model);
}
</div>
<hr />
var listData = (List<HimHer.Models.Stories>)ViewBag.Grid;
WebGrid wgImages = new WebGrid(listData, rowsPerPage: 20);
#wgImages.GetHtml(tableStyle: "table table-condensed table-bordered table-striped table-responsive",
columns: wgImages.Columns(
wgImages.Column
(columnName: "Image", header: "Image"),
wgImages.Column
(columnName: "Story", header: "Story"),
wgImages.Column
(columnName: "Image", header: "Download", format: (testItem) => Html.ActionLink("Download", "DownloadStories", new { filename = testItem.Image })),
wgImages.Column
(header: "Edit", format: (testitem) => Html.ActionLink("Edit", "EditStories", new { ID = testitem.ID, Story = testitem.Story, Image = testitem.Image, HiddenID = 1 }))
)
);
}
<h2>Index</h2>
You code will generate 2 forms and they are nested!.
<form action="/Stories/GetStories">
<form action="/Stories/UpdateStories">
<input type="submit" />
</form>
</form>
Nested forms are invalid! This is the reason, when you click the submit button from inner form from the partial view, it is submitting to the action method defined for the outer form.
You should not be nesting forms. So move out the call to the RenderPartial outside of your BeginForm call.
Looking at the code you shared,there is no need to have the form tag in the main view as you do not have any form data you have to submit. So simply remove that.
If you absolutely want another form in the main view, make sure that, it is not creating a nested form situation. You can have 2 forms parallel in the same view
#using (#Html.BeginForm("GetStories", "Stories", FormMethod.Get))
{
<!-- Some form elements needed for this form -->
}
#{ Html.RenderPartial("EditStories", Model); }

MVC Ajax Beginform doesn't perform client model validation

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.

Categories

Resources