Is it possible to pass inside the options of the "save" method - a diffrent url/path for the request ?
The default urlRot for the model is --> urlRoot: "/users"
is it possible to do something like that:
this.model.save({
'userName': $('#userName').val(),
'password': $('#password').val()},{
url: "/users/login",
success: function(model, response, options) {
},
So the request, this time, will be sent to "/users/login" and NOT to "/users" ?
From the documentation:
urlmodel.url()
Returns the relative URL where the model's resource
would be located on the server. If your models are located somewhere
else, override this method with the correct logic. Generates URLs of
the form: "/[collection.url]/[id]", falling back to "/[urlRoot]/id" if
the model is not part of a collection.
So it looks as if you can provide your own url function on a model.
Example:
var MyModel = Backbone.Model.extend({
use_custom_url: false,
url: function() {
if (use_custom_url) {
return "/users/login";
} else {
return Backbone.Model.prototype.url.apply(this);
}
}
});
Related
I want to do a $.ajax({type: "POST" to a method found in \Pages\PCL\PCL_Index.cshtml.cs. The method signature is public void OnPostUpdateList(int listId, string itemName, bool isRemoving). My attempts always return: POST https://localhost:44360/PCL/OnPostUpdateList 404 (Not Found) or some variety of that 404 message. Here is my jquery:
$.ajax({
type: "POST",
url: "/PCL/OnPostUpdateList",
data: { listId: listId, itemName: itemName, isRemoving: isRemovingChecked },
success: function (result) {
if (result.success) {
console.log(result);
}
else {
alert("Error: " + result.errorMessage);
}
},
error: function (xhr, status, error) {
alert(error);
}
And here are the url: paths I've tried:
url: "/PCL/OnPostUpdateList",
url: "PCL/OnPostUpdateList",
url: "/PCL/UpdateList",
url: "/OnPostUpdateList",
url: "/PCL/?handler=OnPostUpdateList",
url: "/PCL/?handler=UpdateList",
url: "/PCL/PCL_Index?handler=UpdateList",
url: "/PCL/PCL_Index?handler=OnPostUpdateList",
url: '#Url.Page("PCL/UpdateList")',
url: '#Url.Page("PCL/OnPostUpdateList")',
url: '#Url.Page("/PCL/PCL_Index/OnPostUpdateList", "listId", "item", "action")',
url: '#Url.Page("/PCL/PCL_Index/UpdateList", "listId", "itemName", "isRemoving")',
I've added this attribute to my model but it doesn't help: [IgnoreAntiforgeryToken(Order = 1001)].
I was able to reach the wrong post method public async Task<IActionResult> OnPostAsync() used to post the entire form, but that is not wanted. That method was reached when I used these:
url: '#Url.Action("UpdateList", "PCL_Index")',
url: '#Url.Action("OnPostUpdateList", "PCL_Index")',
How can I best troubleshoot this frustrating issue? What is the correct url path?
I'm using ASP.Net Core 6 Razor Pages. My goal is to allow users to add or remove items from drop-down select lists on the page (and the underlying database lookup tables). I want to let them modify lists without updating the entire form that the select lists are within. When the user clicks a button next to each select list a bootstrap modal form pops up allowing the user to add or remove list items. The ajax code is called when the user clicks Save Changes on the modal window.
EDIT: I have just found the problem was caused by some information I did not provide since it was overlooked. Within IIS Express I had set up an App URL of localhost:64373/Lab. So, I have been missing Lab/ from my path. In the future I can post a more complete answer, unless someone else would like to try given this new information.
The problem is solved by using #Url.Content("~/")
To troubleshoot this issue, look at the url (of the page) in each location where the application runs. Here, the deployed url is: https://(Host Name or Domain Name)/PCL. During development the url is: https://localhost:(Your Port)/Lab/PCL. Notice the addition of /Lab on the development machine. This App URL is set in the project properties Launch Profiles for IIS Express.
To resolve the different paths to the application root make use of #Url.Content("~/"). Unfortunately, javascript does not understand #Url.Content("~/") so we build a javascript function called expandPath:
function expandPath(path) {
if (!path) return undefined; if (path.substring(0, 2) === "~/") {
const root = $("body").attr("data-rooturl");
path = root + path.substring(2);
} return path;
}
which points to the body element of the _Layout.cshtml page:
<body data-rooturl="#Url.Content("~/")">
Finally, we call expandPath in the ajax url:
$.ajax({
type: "POST",
url: expandPath("~/PCL?handler=UpdateList"),
data: { listId: listId, itemName: itemName, isRemoving: isRemovingChecked },
success: function (result) {
if (result.success) {
console.log(result);
}
else {
alert("Error: " + result.errorMessage);
}
},
error: function (xhr, status, error) {
alert(error);
}
Notice the use of ?handler=UpdateList to point the method public void OnPostUpdateList. ?handler= is used in the queryString because we want to avoid calling the default OnPost method to prevent posting the full page to the server.
I have a controller (InformationTechnologyController). That controller contains an action (LocationChangeRequest). That action takes an optional parameter(id).
public ActionResult LocationChangeRequest(ChangeRequestType id = ChangeRequestType.WithinDepartment)
That action returns a view with the current model data.
return View(locationChangeRequest);
Within that view, there's a function that performs an ajax post (code below) to search for employee information.
Employee Search 1
The url to reach that view is:
http:// [not relavant here] /InformationTechnology/LocationChangeRequest
When a user attempts to reach that view using a route parameter, the Employee Search function does not perform.
The url to reach the view with the routing parameter is:
http:// [not relavant here] /InformationTechnology/LocationChangeRequest/1
What I discovered is the HttpPost method in the InformationTechnology controller is not being hit when using the /1 parameter in the path. Athough it seems to have to do with the parameter in the path, I can't seem to figure out how to solve the problem.
Any advice on how to handle hitting the HttpPost through the url with the parameter would be appreciated.
The HttpPost code is as follows:
[HttpPost]
public JsonResult SearchUser(string term)
{
...
return Json(results, JsonRequestBehavior.AllowGet);
}
The javascript code is as follows:
$.ajax({
url: searchUserUrl,
type: "POST",
dataType: "json",
data: { term: request.term },
success: function (data) {
response($.map(data,
function (item) {
return { label: item.Name, value: item.HexKey }; }));
},
error: function (xhr, error) {
console.debug(xhr); console.debug(error);}
})
You need to define a global variable for using the $ as below.
var $=jQuery.noConflict();
I'm having troubles catching a response from Rails controller upon saving a model. I can see that the XHR response is generated in the Network tab of Chrome's devtools, but success or error functions don't fire. I suspect that this is a consequences of forcing post method and different url directly in the view, but I'm not sure, maybe I've messed up some syntax. Here's the snippet of the the save function in coffee:
save: (user_id) =>
model = #model
if $(".task").val()
#$el.find(".task").each ->
model.set
body: #value
user_id: user_id
task_title_id: model.id
return
model.save null, type: 'post', url: '/tasks',
success: (model, response) ->
console.log 'tasks saved!'
error: (model, response) ->
console.log "error! ", response.responseText
else
console.log 'nothing to save'
and compiled JS:
save = function(user_id) {
var model;
model = this.model;
if ($(".task").val()) {
this.$el.find(".task").each(function() {
model.set({
body: this.value,
user_id: user_id,
task_title_id: model.id
});
});
return model.save(null, {
type: 'post',
url: '/tasks'
}, {
success: function(model, response) {
return console.log('tasks saved!');
},
error: function(model, response) {
return console.log("error! ", response.responseText);
}
});
} else {
return console.log('nothing to save');
}
};
Trivia: I have to generate a new Task view for each existing TasktTitle and then submit these new Tasks to the server. Being very new to the Backbone I couldn't come up with a better idea other than render TaskTitles collection and add input field for each TaskTitle view and then force post method and /tasks url on save. It does feel quite dirty, but it works as expected with the exception of catching the response, which is a crucial part because there is more logic happens on success\error.
In asp I have a function as:
public async Task<IHttpActionResult> updateComment(int id, Comment comment)
{
//some stuff
}
To send data to this function I have created an ojbect as (I am working with knockout.js):
var com = {
id: self.id,
description: self.description,
postedBy: self.postedById,
time: new Date($.now()),
adId: self.adId,
};
And in ajax request I am sending data as:
$.ajax({
url: '/api/Comment/updateComment',
dataType: "json",
contentType: "application/json",
cache: false,
type: 'POST',
data: { id: com.id, comment: com },
success: function (data) {
alert("done");
},
error: function () {
alert("error");
}
});
But request does not goes to above asp.net function. I got error in browser console window 404 (Not Found) . Error is because it is not receiving comment object as it was expecting. I changed ajax request method to get to see url and url is below.
Is there something wrong with my defined com function? Why its not working?
Update:
public async Task<IHttpActionResult> updateComment()
{
//some stuff
}
I changed the function as above and its working fine. So it is confirmed that is some problem with com object. Function is not receiving object as it was expecting.
Update 2:
Now I changed function parameters to:
public async Task<IHttpActionResult> updateComment(Comment comment)
{
//some stuff
}
and send data as:
data: ko.toJSON(com),
and its again working fine!
error code is 405:Method not allowed i guess this is something like, your ajax is type:"Post" request but your backend is expecting some GET requests.
Another suggestion is that you can send a stringified object with this:
data : '{ "id":"' + com.id + '", "comment":"' + com + '"}',
If you are using ajax post with two parameters class object and other type you need to create other obj like below:
Note: Make sure that all properties of com object are same like your Comment class.
var com = {
id: self.id,
description: self.description,
postedBy: self.postedById,
time: new Date($.now()),
adId: self.adId,
};
var obj = {};
obj.id = com.id;
obj.comment = com;
And pass data using JSON.Stringy(obj) like below:
data: JSON.stringify(obj),
I had tested the code it is working check below screen shot:
This is basically what the original problem reduces to:
I have a Backbone model and I want to execute a certain action every time it saved successfully, but not after it's fetched. The cleanest and least intrusive way to do this, as I see it, would be to attach a handler to the sync event and check the XHR object: if it's a response to a GET, do one thing, and another if it was a POST.
However, looks like I cannot determine the HTTP method the jqXHR was created in response to... or can I?
You can override the Backbone.sync method like this :
var sync = Backbone.sync;
Backbone.sync = function(method, model, options) { // override the Backbone sync
// override the success callback if it exists
var success = options.success;
options.success = function(resp) {
if (success) success(model, resp, options);
// trigger the event that you want
model.trigger(methodMap[method]);
};
sync.call(this, method, model, options);
};
methodMap looks like :
var methodMap = {
'create': 'POST',
'update': 'PUT',
'patch': 'PATCH',
'delete': 'DELETE',
'read': 'GET'
}
So in order to catch the GET/POST method all you have to do is :
initialize: function() { // your view initialize
this.listenTo(this.model, "GET", /* your GET callback */);
this.listenTo(this.model, "POST", /* your POST callback */);
}
You can override the save method to do whatever you want; something like this:
#MyApp.module "Entities", (Entities, App, Backbone, Marionette, $, _) ->
class Entities.Model extends Backbone.Model
save: (data, options = {}) ->
## do whatever you need to do ##
super data, options
Then just extend your models from this definition instead of Backbone.Model, like so:
class Entities.MyModel extends App.Entities.Model