have implemented filtering on my ASP.NET MVC 5 app.
My searchbox consists of a few Dropdownlists with predefined values. When the Dropdownlist value changes, the form is submitted and I see all available tickets for a specific method.
After the form submits the page reloads and I see the url like mysite.com/?Method=car. But I would like to get rid of the query string and put car directly into the url, i.e.
mysite.com/method/car or mysite.com/method/plain etc
Is it possible?
Search box
#using (Html.BeginForm("Search", "Transfer", FormMethod.Get))
{
<div class="form-horizontal">
<div class="form-group">
<div class="col-md-10">
#Html.DropDownListFor(model => model.Method, Model.Methods, new { #class = "query"})
</div>
</div>
</div>
<input type="submit" class="hidden" />
}
My action method
[Route("~/transfer/{method?}")]
public async Task<ActionResult> List(string method)
{
//filter and displaying
return View(viewModel);
}
By default Html.BeginForm with FormMethod.Get will serialize all the form values into query string. So if you want friendly URLs you will have to write some JavaScript (jQuery in this example).
First of all you can remove the form
<div class="form-horizontal">
<div class="form-group">
<div class="col-md-10">
#Html.DropDownListFor(model => model.Method, Model.Methods, new { #class = "query"})
</div>
</div>
</div>
<button type="button" id="submitMethodBtn">Submit</button>
<script>
var baseUrl = '#Url.Action("Search", "Transfer")/'
$('#submitMethodBtn').click(function(){
var url = baseUrl + $(#'#Html.IdFor(m=>m.Method)').val();
window.location.href = url;
})
</script>
Some issues/clarifications:
1if you enter mysite.com/method/car (assuming that issue #2 is resolved )in browser it will take you to a correct action so your issue is basically generating friendly Url in the view.
2 In the provided code example i used an inline script. You can extract it to a separate static file but you will have to hard-code the url and the html id for Method property.
3 Your action method gets int as parameter so how do you expect it to work with mysite.com/method/car (car is a string) ?
You can call an ajax method on page which will avoid query string and when controller redirects to ActionResult then again you can call ajax method on redirected page. By this way you can avoid query string in MVC.
Take below code as example.
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "Transfer/search",
data: "{ID:1}",
dataType: "json",
error: function(xhr, ajaxOptions, thrownError) { alert(xhr.responseText); }
});
Make return type as JsonResult of controller method.
Related
I have a html form in which I write in a text box and submit when press a button and it saves in db but I want the page not to refresh and continue with the values in the text box
I have see people talking about ajax but I have never worked with ajax
<div class="row" style="float:left; margin: 2px ">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="col-md-3">
<div class="form-group">
<label>Pressão Injeção:</label>
<input id="id3" type="text" name="Pressão_de_Injeção" /> <br />
</div>
</div>
Here is a quick example of an AJAX call which will POST data to an controller:
var menuId = $("ul.nav").first().attr("id");
var request = $.ajax({
url: "Home/SaveForm",
type: "POST",
data: {id : menuId},
dataType: "html"
});
request.done(function(msg) {
console.log('success');
});
request.fail(function(jqXHR, textStatus) {
alert( "Request failed: " + textStatus );
});
Note, that you can also pass objects to the controller by supplying them as an variable within the data object:
var menuId = $("ul.nav").first().attr("id");
var obj = {
id: menuId,
text: "Foo"
};
var request = $.ajax({
url: "Home/SaveForm",
type: "POST",
data: {name: "Jim", object: Obj},
dataType: "html"
});
(Code adapted from an answer by apis17.)
An introduction to AJAX, can be found here:
https://www.w3schools.com/js/js_ajax_intro.asp
The only other method of performing what you required (without using AJAX) is to use a form submit and pass the data back to the HTML form once complete. You would then need to re-populate the fields (however, this will cause additional work on both submitting and re-populating, if (and/or when) new fields are adding if the future).
You will have to take the ajax approach.
But if you don't want to do that, you can always post to the controller and return the model to the view. It will have the text you entered into the textbox.eg.
public IActionResult MyView()
{
return View();
}
[HttpPost]
public IActionResult MyView(MyModel model)
{
return View(model);
}
Hope this helps as an alternative.
I have an issue where the hidden values in a form are not updating when the new ActionResult is returned.
For example, a user will check several records and click the Update Completion button. This makes an Ajax called to the UpdateCompleted action that sets a date for the checked records and once the Ajax call returns the form is submitted. After performing some logic in the form submit Action method, an updated model is returned with the IsChecked value set to false for all records in the model, but the form is retaining the previous checked value due to the generated id below having the same value.
Code
<td>
#Html.CheckBoxFor(model => Model.WorkOrderDetails[x].IsChecked)
#Html.HiddenFor(modelItem => Model.WorkOrderDetails[x].IsChecked)
#Html.HiddenFor(modelItem => Model.WorkOrderDetails[x].WorkOrderEntityId)
#Html.HiddenFor(model => model.WorkOrderDetails[x].WorkOrderId)
</td>
Rendered HTML
<td>
<input data-val="true" data-val-required="The IsChecked field is required." id="WorkOrderDetails_0__IsChecked" name="WorkOrderDetails[0].IsChecked" type="checkbox" value="true"><input name="WorkOrderDetails[0].IsChecked" type="hidden" value="false">
<input id="WorkOrderDetails_0__IsChecked" name="WorkOrderDetails[0].IsChecked" type="hidden" value="False">
<input id="WorkOrderDetails_0__WorkOrderEntityId" name="WorkOrderDetails[0].WorkOrderEntityId" type="hidden" value="ODU=">
<input id="WorkOrderDetails_0__WorkOrderId" name="WorkOrderDetails[0].WorkOrderId" type="hidden" value="NjQ4OTU3">
</td>
Submit Code
#using(#Html.BeginForm("Index", "WorkOrderMaster", FormMethod.Post, new { id = "workOrderMasterForm" }))
{
<div>
<div class="project-buttons">
<div class="btn-group">
<input id="submitCompletion" class="btn btn-success" value="Update Completion" data-submit-url='#Url.Action("UpdateCompleted", "WorkOrderMaster")' />
</div>
</div>
$(function () {
$('#submitCompletion').click(function () {
$.ajax({
type: 'POST',
url: $(this).data('submit-url'),
data: $('#workOrderMasterForm').serialize(),
success: function (data) {
$('#workOrderMasterForm').submit();
}
});
});
});
I would expect the new values from the model to be used but this is not occurring.
Is it recommended to code the input values manually in this situation in order to avoid the following format?
ClassName_Index_PropertyName
Thanks in advance for the time you took to look at this question.
Based on the provided code, you are performing an AJAX call to the server but expects the values to be cleaned up after the operation is finished.
It will not work since you are not refreshing the page. To clean up the form values without refreshing the page you need to do a small change in your code:
$(function () {
$('#submitCompletion').click(function () {
$.ajax({
type: 'POST',
url: $(this).data('submit-url'),
data: $('#workOrderMasterForm').serialize(),
success: function (data) {
$('#workOrderMasterForm').reset();
}
});
});
});
The change is in the success promise where "$('#workOrderMasterForm').sugmit();" changed to "$('#workOrderMasterForm').reset();".
In an effort to keep moving on this. I moved the form to a partial view, and added a div to load the partial view into. Anytime an event fires on the page thru many filters or the users submitting checked records the div is cleared and reloaded. This solved my issue.
I have a view with a button, when click this button, an ajax function calls controller method ApplicationAndUse which is supposed to pass a list to a partial view included in my view. The partial view content is supposed to be refreshed, but this doesn't work, my partial is still empty.
My code :
Main view :
#model List<String>
<div class="row">
<div class="col-md-2">
#foreach (var item in Model)
{
<div id="univers-#item" class="btn btn-info">#item</div><br />
}
</div>
<div class="col-md-10">
#Html.Partial("_ApplicationAndUsePartial", null, new ViewDataDictionary())
</div>
</div>
#section scripts
{
<script type="text/javascript">
$(function () {
$('[id^=univers]').click(function () {
var selectedButton = $(this).attr('id');
var selectedUniverse = selectedButton.substring(selectedButton.indexOf('-') + 1, selectedButton.lenght);
$.ajax({
url: "http://" + window.location.host + "/UseAndNeed/ApplicationAndUse",
type: "POST",
data: { idUniverse: selectedUniverse },
dataType: "json",
});
});
});
</script>
}
Partial view :
#model List<int>
#if (Model!= null) {
foreach (var item in Model)
{
<div id="ApplicationUse-#item" class="btn btn-default">#item</div><br />
}
}
Controller function :
[OutputCache(Duration = 0)]
public ActionResult ApplicationAndUse(String idUniverse)
{
List<int> items = new List<int>();
items.Add(1);
items.Add(2);
return PartialView("_ApplicationAndUsePartial", (object)items);
}
what do i miss?
Give a unique Id to the div where we want to show the partial view content.
<div id="myPartial" class="col-md-10">
#Html.Partial("_ApplicationAndUsePartial", null, new ViewDataDictionary())
</div>
And in the success handler of the ajax method, update this div's innerHTML with the response coming from the ajax call. Also you do not need to pass specify the dataType value when making the ajax call.
var myUrl= "http://" + window.location.host + "/UseAndNeed/ApplicationAndUse";
$.ajax({ type: "POST",
url : myUrl,
data: { idUniverse: selectedUniverse },
success:function(result){
$("myPartial").html(result);
}
});
Always you should use the Url.Action or Url.RouteUrl html helper methods to build the url to the action methods. It will take care of correctly building the url regardless of your current page/path.
var myUrl= "#Url.Action("ApplicationAndUse","UseAndNeeed")";
This works if your js code is inside the razor view. But If your code is inside a seperate javascript file, you may build the url(s) in your razor view using the above helper methods and keep that in a variable which your external js file code can access. Always make sure to use javascript namespacing when doing so to avoid possible issues with global javascript variables.
#section Scripts
{
<script>
var myApp = myApp || {};
myApp.Urls = myApp.Urls || {};
myApp.Urls.baseUrl = '#Url.Content("~")';
</script>
<script src="~/Scripts/PageSpecificExternalJsFile.js"></script>
}
And in your PageSpecificExternalJsFile.js file, you can read it like.
var myUrl= myApp.Urls.baseUrl+"UseAndNeed/ApplicationAndUse";
$("#myPartial").load(myUrl+'?idUniverse=someValue');
I've been trying to add some Ajax functionality to my mvc site, however, I run into a problem regarding page refreshing. I've created an rss view on my homepage sidebar, which allows the user to select which rss feed they want to view using a drop down list. Initially I was using the html.begin form option in mvc, however, I decided it would be a cool feature to have the rss feeder refresh, rather than having the whole page refresh. I implemented the ajax.begin form, but the whole page is still refreshing.
Here is the code inside my view:
<div class="rss_feed">
<h3>RSS Feed</h3>
#using (Ajax.BeginForm("Index", "Home",
new AjaxOptions
{
HttpMethod = "post",
UpdateTargetId = "feedList"
}))
{
#Html.DropDownListFor(x => x.SelectedFeedOption, Model.FeedOptions)
<input type="submit" value="Submit" />
}
<div id="feedList">
#foreach (var feed in Model.Articles)
{
<div class="feed">
<h3>#feed.Title</h3>
<p>#feed.Body</p>
<p><i>Posted #DateTime.Now.Subtract(#feed.PublishDate).Hours hour ago</i></p>
</div>
}
</div>
</div>
When the user selects a feed type from the drop down menu, and clicks the submit button, the feed should update to the selected option.
In the _Layout view the following bundle is loaded:
#Scripts.Render("~/bundles/jquery")
Any help would be great.
I use an ajax call in jquery for this
$('#SelectedFeedOption').change(function() {
$.ajax({
url: "#(Url.Action("Action", "Controller"))",
type: "POST",
cache: false,
async: true,
data: { data: $('#SelectedFeedOption').val() },
success: function (result) {
$(".feedList").html(result);
}
});
});
Then put the contents of your feedList div in a partial view and on your controller
public PartialViewResult FeedList(string data){
Model model = (get search result);
return PartialView("_feedList", model);
}
Hopefully this helps.
Did you try initializing the InsertionMode member into the AjaxOptions object initializer?
You also have to include 'jquery.unobtrusive-ajax.js' to make Ajax.BeginForm to work as answered here
#using (Ajax.BeginForm("Index", "Home", null,
new AjaxOptions
{
HttpMethod = "post",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "feedList"
});
{
#Html.DropDownListFor(x => x.SelectedFeedOption, Model.FeedOptions)
<input type="submit" value="Submit" />
}
I have this script, what it intends to do is: in a view with a list of contacts, each one with a edit link whenever you click on one of these links it displays an edit form in a partial view (there's only one div in the parent view for holding it) just below the clicked contact, for that it does a get ajax call to the server and gets the information for that contact. After submitting, via ajax as well, it refreshes the list.
Everything seems to work fine, but if I edit a contact, after the list being refreshed I try to open again the form on the same contact and the information is the same as it was before being edited. Although debugging I see the list for the server is correct (and so is the display in the list, it's only wrong in the form)
Thing is that in chrome developer tool I can see the form with some "default values" set to the previous stuff. I didn't know about them till now and I don't know how to get rid of them, because to my understanding I'm making a get call to the server, anyway I have tried this
document.getElementById("editForm").reset();
with no luck.
Thanks
The script
(function ($) {
var editContainer = $(document.getElementById('editContainer'));
$('#editContainer').on('submit', '#editForm', ajaxEditCall);
$('a.edit').on("click", displayEditForm);
function displayEditForm(e) {
var clickedElement = $(this).parent(),
url = editContainer.data('amp-edit-url');
$.get(url, {
id: parseInt(this.id, 10)
}, function (result) {
editContainer.html(result);
$.validator.unobtrusive.parse(editContainer);
// Display edit form just below the "item" clicked
if (editContainer.is(":visible")) {
editContainer.slideToggle(300, function () {
editContainer.appendTo(clickedElement);
editContainer.slideToggle(300);
});
} else {
editContainer.appendTo(clickedElement);
editContainer.slideToggle(300);
}
}, "html");
e.preventDefault();
}
function ajaxEditCall(e) {
e.preventDefault();
//if ($('#editForm').valid()) {
var list = $(document.getElementById('list'));
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (result.passedValidation == true) {
$.get(result.action, function (partial) {
document.getElementById("editForm").reset();
list.html(partial);
$('a.edit').on("click", displayEditForm);
$('#editForm').slideUp(300);
setTimeout(function () {
list.effect("highlight", {}, 3000);
}, 1000);
});
} else {
$(document).scrollTop(0);
editContainer.html(result);
$.validator.unobtrusive.parse('#editForm');
}
}
});
//} return false;
}
}(jQuery));
And the view in case is relevant
#model ContactListViewModel
#{
ViewBag.Title = " My Contacts";
}
<div id="myContacts">
<h2>My Contacts</h2>
<div id="editContainer" data-amp-edit-url="#Url.Action("Edit", "Contacts")" class="initiallyHidden"></div>
<div id="list">
#{ Html.RenderPartial("_ContactList", Model); }
</div>
<div id="dialog" data-amp-del-url="#Url.Action("Delete", "Contacts")" title="Confirmation Required">
<p>Are you sure you want to delete this Contact?</p>
</div>
</div>
#section Foot
{
<script src="~/Scripts/AMPContacts.js"></script>
<script src="~/Scripts/conditional-validation.js"></script>
<script src="~/Scripts/Placeholders.min.js"></script>
}
Well that's obviously the parent view, the partial one is just a bunch of fields, I remove most of them to avoid increase the already long post
#model AddContactViewModel
#using (Html.BeginForm("Edit", "Contacts", FormMethod.Post, new { #id = "editForm", #class = "addTab" }))
{
#Html.ValidationSummary(true, "Please correct the errors and try again.")
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.OwnedItemId)
#Html.HiddenFor(m => m.AddressId)
<div id="editContactDetails">
<div>
#Html.DisplayFor(m => m.PlanName)
</div>
<div>
#Html.DropDownListFor(m => m.Title, Model.TitleList, "Title")
</div>
<div>
#Html.EditorFor(m => m.FirstName, new { #id="editFirstName", data_placeholders_focus = "false", placeholder = ViewData.ModelMetadata.Watermark })
#Html.ValidationMessageFor(m => m.FirstName)
</div>
// And so on....
<div class="addDEC">
<input class="addDECButton" type="submit" value="Save" />
</div>
}
I ran into this problem with a site I was working on. You'll need to disable your ajax caching:
//Disbable cache for all jQuery AJAX requests
$.ajaxSetup({ cache: false });
That will do it for all ajax calls, so you may only want to do that on certain pages, depending on your usage.