Ajax Request that Post back a new page instead of loading partial - asp.net

I have this HTML code in my view
#using (Ajax.BeginForm("AddJoke", "Home", new AjaxOptions { HttpMethod = "GET", UpdateTargetId = "MyfriendsJokes" , InsertionMode= InsertionMode.InsertAfter}))
{
<div style="display:block">
<textarea placeholder="Post New Joke" id="newJoke" name="joke" rows="3" cols="50" style="float:left;position"></textarea>
<button type="submit" id="postnewjoke" style="float:left"> Post </button>
#Html.TextBoxFor(model => model.fileContent, new { type = "file", id = "fileuploaded", name = "fileuploaded" })
<div style="display:inline-block">
<input type="checkbox" name="geo" id="geo" style="width: 100%; float: left; display: block">
<input name="longitude" style="display:none"/>
<input name="latitude" style="display:none" />
<input name="user" style="display:none" value="#Model.user.Id"/>
<span>Include Location</span>
</div>
<span id="jokeError" style="color:red;font-size:14px;"></span>
</div>
}
<article id="MyfriendsJokes">
#Html.Partial("_NewJoke")
</article>
and this code in my controller
[HttpPost]
public PartialViewResult AddJoke(string joke, string user, HomePage page,HttpPostedFileBase fileuploaded, string longitude, string latitude)
{
Joke newJ = new Joke();
newJ.Key = Guid.NewGuid();
newJ.body = joke;
newJ.facebookID = user;
newJ.rank = 0;
newJ.time = DateTime.Now;
newJ.longitude = longitude;
newJ.latitude = latitude;
db.Jokes.Add(newJ);
HomePage page1 = new HomePage();
page1.user = Session["user"] as MyAppUser;
//db.SaveChanges();
return PartialView("_NewJoke", page1);
}
but instead of adding elements to the targeted div, it reload the page with a new whole page with just the elements of the partial view which is this
#using Jokes.Models
#using Microsoft.AspNet.Mvc.Facebook.Models
#model HomePage
<div style="display:block">
#Model.user.Name
</div>
can someone help and say what's wrong here to append elements to div instead of loading a new whole page?

Make sure that the jquery.unobtrusive-ajax.js script is referenced in your page. This is what AJAXifies all the output generated by the Ajax.* helpers. Without this script you only get a standard <form> element generated by the Ajax.BeginForm with a bunch of data-* attributes. The jquery.unobtrusive-ajax.js script analyzes those data-* attributes and subscribes to the submit event of the form, canceling the default action of making a full postback and sending an AJAX request to the server based on the data-* attributes.
It's important to mention that this script must be included AFTER jquery.js because it depends on it.
Also you seem to have some file input in your form and your controller action is taking an HttpPostedFileBase parameter. You should realize that you cannot upload files using an AJAX request and once you include this script your file uploads will simply stop working. In order to be able to upload files using AJAX you could either use some plugin such as jquery.form and Blueimp file upload or you could directly use the new XMLHttpRequest object that's built into modern browsers. The advantage of the plugins is that they do feature detection and will fallback to other techniques depending on the capabilities of the client browsers.

Related

Downloading a file in the current View, or in a new one

It is necessary that the file is downloaded either staying on the current page, or a new one opens. Tell me how to do it. Here is what has already been done.
public FileResult DownloadFile(int id)
{
FilesDB filesDB = _context.FilesDB.Find(id);
filesDB.DownloadCount++;
_context.SaveChanges();
string downloadName= filesDB.FileDisplayName +
Path.GetExtension(filesDB.FilePath);
return File(filesDB.FilePath, filesDB.FileType, downloadName);
}
You can download both way. Just use HTML form.
Here I'm using WebService:
<form id="downloadForm" action="MyService.asmx/DownloadFile" method="post" target="_self" >
<input type="hidden" name="id" id="txtID" />
</form>
JS:
function downloadFile() {
$('#txtID').val(id);
$('#downloadForm').submit();
}
Just call downloadFile() and this will download staying on current page.
If you want to open in new one just change target="_self" to target="_blank"

ASP.NET web forms change bootstrap theme dynamicly

my main problem is that I want to change the bootstrap theme of my Website with a Dropdown list of themes and a button.
#model IEnumerable<ProjectManagementTool.ServiceReference1.Theme>
#{
ViewBag.Title = "Settings";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<form action="/Home/Settings" method="get">
<h2>Settings</h2>
<br />
<h4>Change Theme</h4>
#Html.DropDownList("GetThemes", null, htmlAttributes: new { #class = "form-control" })
<br />
<p>
<input class="btn btn-default" type="submit" value="Save"/>
</p>
#foreach (var item in Model)
{
#Html.DisplayFor(modelItem => item.Path)
<br/>
}
</form>
The foreach loop is just to show the diffrent paths.
I have a database aswell with a themes table:
Now the question is, how can I change the bootstrap?
I know that there is this code tho change the theme.
#Styles.Render("~/Content/flatly.bootstrap.css")
But it should be in the _layout.cshtml file to set it for the whole website.
The background is working with a service but this is not important here.
Screenshot of the website:
You could write an action that returns the path of the css file to be used depending on the user settings.
Something along the lines of
#Styles.Render(Html.Action("UserCssPath", "Settings").ToString());
Because you don't have access to a ViewModel in your layout page, the controller must use another mechanism to find out for which user the action was invoked. For example, we store a User Context object with the required data in the HttpContext.Current.Session. This could be written once on logon. The UserCssPath action can then access the DB to find the correct CSS path and return it: return Content(cssPath);

How does #Html.BeginForm() work? and search result in Microsoft ASP.Net MVC 5 tutorial?

I am working on MVC 5 Asp.Net and following this tutorial. I am wondering how the heck does this fetch the result when I click the Filter button?
There comes a point where this code is added in Movie/view/Index.cshtml
#using (Html.BeginForm())
{
<p> Title: #Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
Now as far as I know, it creates a textbox and a button on screen. But how is this button calling the search(index) function and passing the value of textbox in the function, I could not get this.
It's not a stupid question. #html.BeginForm() works like this. It has some parameters you could add to it like Action Controller FormType htmlAttributes. The way it works is that if you leave it empty it will look for a post action with the same name that on the page you are now, for example if you are in on the login page, it will look for a login post action. I always write what action and controller I want it to access.
#Html.BeginForm("AddUser", "Admin", FormMethod.Post, new { #class = "my_form"}) {
}
So your post action should accept parameters that your form contains, and that can be a Model ie a Product, ViewModel or single string parameters. In your case with the search your action should look like
[HttpPost]
public ActionResult Search(string SearchString)
{
//do something here
}
Please note here, for the search string to be passed into the method. The name of the <input> has to be the same as the parameter your action takes. So our form should be like this
#using (Html.BeginForm("Search", "YOUR CONTROLLER", FormMethod.Post)){
<p> Title: #Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
Hope this brings clarity.

ASP.NET MVC pass data from partial view

How can I pass data from partial view on submit form in ASP.NET MVC.
#using (Html.BeginForm("Edit", "BlogPost", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
................
#Html.Partial("PostImagesForPost",Model.PostImages)
}
PostImagesForPost - partial view:
#model IEnumerable<Blog.Models.PostImage>
<script type="text/javascript" src="~/Scripts/jquery.zoom.min.js"></script>
<div>
#{
List<Blog.Models.PostImage> images = Model.ToList();
<ul class="images">
#foreach (var img in images)
{
string parameterValue_small = "~/BlogPhotos/120/" + img.Photo.ToString();
string parameterValue_big = "~/BlogPhotos/600/" + img.Photo.ToString();
<li>
<div id="jquery-image-zoom-example">
<span data-postid="#img.ID" data-delete="true" class="deletespan"></span>
<a href="#Url.Content(parameterValue_big)">
<img src="#Url.Content(parameterValue_small)" data-postid="#img.ID" class="zm" onclick="$('.jquery-image-zoom img').click()" />
</a>
<input type="checkbox" checked="checked" name="selectedImagesForDelete" style="display:none;" data-postid="#img.ID" value="#img.ID" />
</div>
</li>
}
</ul>
}
On submit function the parameter selectedImagesForDelete is null.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(Post post,string[] selectedImagesForDelete)
{...........}
This has nothing to do with the fact you're using a partial, and everything to do with how the modelbinder in MVC works. For iterable posted items, the model binder expects field names in the form of ListProperty[index].ModelProperty. The problem is that the Html.* family of helpers will not create this name properly unless they are passed an indexed value, which you can't achieve with foreach. The solution is to simply use for, instead:
#for (var i = 0; i < images.Count(); i++)
{
Html.EditorFor(m => image[i].SomeProperty)
}
By passing in a value that's indexed (images[i]), the helper recognizes that it needs to add the proper indexed html prefix to the name, so that the modelbinder will understand where to stuff the value when it's posted back.
Though, in your case, you seem to actually just be manually specifying the HTML for the fields, which is fine, but you're responsible at that point for getting the name values right.
I believe your name property needs to have indexes in the name:
Create a index variable called index and increment it after each iteration
<input type="checkbox" name="selectedImagesForDelete[index]" value="2">
Actually it was a problem with the javascript file. The checkboxes were never checked.
<input type="checkbox" name="selectedImagesForDelete" value="#img.ID" />
But I resolved that problem and now everything works like expected.
But thanks for trying to help me. I appreciate it.

Passing so far entered data to controller

In a form I have different fields (name, age, ...) and the possibility to upload an image. This I want to realize on a different view. The problem is that the data, that is made so far, are not passed to the controller when I want to change the controller. Here a small example of my code:
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Person</legend>
#Html.EditorFor(model => model.Name)
#Html.EditorFor(model => model.Age)
<img src="#Url.Content(Model.ImagePath)" alt="Image" class="imagePreview" />
<li>
#Html.ActionLink("Upload a pic from you!", "UploadImage", new { model = Model }, null)
#* This is the 'problematic' action *#
</li>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Here the method that is calling the upload controller:
public ActionResult UploadImage(Person model)
{
// properties in the passed model are not set
return RedirectToAction("UploadImage", "UploadImage");
}
How it is possible to get the entered information without using the submit button?
Check out this blog post by Bryan Sampica on asynchronus file uploads with MVC. We just used it for a smooth async file upload experience so we didn't have to leave the page. This solves your problem of how to persist the transient data. If your users are using a modern browser (IE 10+, Chrome, FF, etc...) the progress bars actually show file upload progress. It's fairly easy to setup, but, if you follow the instructions to the letter, does require that you add a webAPI controller to your project.

Resources