I am toying with Ajax-Enabled WCF services. So far I've managed to create and consume my service with a small client application. However while reading the "How-to" page on the msdn website, I've came accross this piece of code :
function Button1_onclick() {
var service = new SandwichServices.CostService();
service.CostOfSandwiches(3, onSuccess, null, null);
}
function onSuccess(result) {
alert(result);
}
and I fail to understand (or even find information about) the null, null parameters when calling the function. 3 is the parameter you want to pass to the service function, onSuccess is the function that is called on a successfull callback but what are those 2 null parameters ?
The last two parameters refer to onFailure and Usercontext respectively for below mentioned question.
service.CostOfSandwiches(3, onSuccess, null, null);
OnFailure : As the name suggest, if ajax call fails because of network issue, server error, timeout etc.., function passed here as argument will invoked.
UserContext: Generally all ajax call (I mean this[WCF Ajax] is too dependent on ajax call) uses this parameter. Because, there is a main method that call $.ajax, in your case it is Button1_onclick. So upto this point all variables defined will not be available in callbacks ( success or failure), because these are called back when ajax call completes, but to make those call aware of previously defined variable, context option is used to pass them.
Example:
function Button1_onclick() {
var service = new SandwichServices.CostService();
var some_var = "someval"; // on successcallback if you are trying to access this, it will show error.
service.CostOfSandwiches(3, onSuccess, null, null);
}
To use this in success callback , you have to pass that as usercontext object -- like this service.CostOfSandwiches(3, onSuccess, null, some_var);
OnSuccessMethod -
function onSuccess(result,usctx,methodname)
{
if (usctx == "someval")
{
alert(result);
}
}
For more info on context option in general ajax sense , refer this - How to pass context in jquery ajax success callback function
They are callbacks for sucess, error, and userContext. You can read a bit more here under the "Accessing WCF web services" section.
Related
I have a method in .NET (GetDataStationParts), which I declare with 2 parameters, I want to call it from a JavaScript, and I use the InvokeMethodAsyn function in this way:
const { data } = require("jquery");
function GetParteScrap()
{
var idestacionjs = document.getElementById('getestacion');
var idmodelojs = document.getElementById('getmodelo');
var tablascrap = DotNet.InvokeMethodAsyn("YMMScrapSystem", "GetDataStationParts", idestacionjs, idmodelojs);
console.log(tablascrap);
}
To do it, I base it on an example on the web but I'm not sure where it gets the DotNet object to then invoke the method, the intention of my code is that after selecting parameters of 2 , go to the database and execute a SQL-level function, which will return a table, with the function GetDataStationParts, I try to give it the functionality to execute my method at the DB level as follows
[JSInvokable]
public async Task<IEnumerable<GetEstacionParte>>GetDataStationParts(int modelo, int estacion)
{
var resul = await _context.Set<GetEstacionParte>().FromSqlInterpolated($"SELECT * FROM dbo.GetEstacionParte({modelo},{estacion})").ToArrayAsync();
return resul;
}
The SQL level function works correctly, but when running the application at the console level in the browser, it throws the following error, where it indicates that the function is not defined
Where could the error be? Thank you for reading
require() is not a feature that is built into the browser. Javascript environment does not understand how to handle require(), In Node.js by Default this function is available.
I suspect you most probably missing some reference here. You can either download require.js from here & link with your application or use below script tag.
<script src="https://requirejs.org/docs/release/2.3.5/minified/require.js"></script>
I'm trying to put together my first CRUD app using AngularJS and Asp.Net Web Api. I have setup the controller with a newMember object:
$scope.newMember = {};
And then call the insert in the factory method as:
dataService.insertMember($scope.newMember);
This calls the method in the dataService:
var _insertMember = function(member) {
return $http.post("/api/clubmembers/", member);
};
which fires the Web Api Post method
public HttpResponseMessage Post([FromBody]PersonViewModel member)
{
//if (_repo.AddClubMember(member) && _repo.Save())
if (_repo.AddClubMember(member) && _repo.Save())
{
return Request.CreateResponse(HttpStatusCode.Created, member);
}
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
I have checked the data in the Angular part of the app and the correct data is passed via $scope.newMember, but when it reaches the Web Api Post method the member parameter is always Null.
If I modify the controller method to the following it passes the data to the Post method as expected:
var testData2 = {
FirstName: $scope.newMember.FirstName,
LastName: $scope.newMember.LastName
};
var a = 1;
dataService.insertMember(testData2);
Is it possible to pass $scope.newMember as the parameter or do I have to fill in the details as of the amended code?
Thanks
Mark
Check your code carefully, I would say (based on your experience described in the question) there will be some typo.
Call with explicit {} - empty object
If you will call your service like this:
dataService.insertMember({}); // just created empty object
you will get instantiated object on your API Post method PersonViewModel member
Call with explicit null or undefined
but in case, that you will call one of these
dataService.insertMember(null);
dataService.insertMember(undefined);
the API Post method will be provided with NULL.
typo (incorrect property name), i.e. undefined
And what that means? that you most likely, somewhere in the call chain used something like this
$scope.newMember ...
...
dataService.insertMember($scope.newMemberXXX);
where newMemberXXX represents any undefined property, resulting in undefined to be passed
If you add FirstName and LastName properties to newMember it should work fine:
$scope.newMember = {};
$scope.newMember.FirstName = "First Name";
$scope.newMember.LastName = "Last Name";
dataService.insertMember($scope.newMember);
Thing is, $scope.newMember has to match the properties and structure of PersonViewModel for the Web Api to be able to match the two types.
Let us know if this works.
Let's say we have a standard Ajax form with the following Syntax:
#using(Ajax.BeginForm("AddCityJson", "City",new AjaxOptions
{
HttpMethod = "post",
OnSuccess = "JScriptOnSuccess();",
OnFailure = "JScriptOnFailure"
}))
{
...form fields go here...
}
A simple form that gathers some information about a city, submits and saves it.
On the controller side we receive the info. If everything went well we return true in order for OnSuccess AjaxOption to trigger and if failed false is returned:
public JsonResult AddCityJson(Formcollection collection)
{
var city = new City
{
...populate city fields from passed in collection
}
var cityRepository = new CityRepository;
city = cityRepository.SaveOrEdit(city);
if(city==null)
{return Json(false)}
return Json(true);
}
Inside of the controller AddCityJson method I need to add various checks. Possibly to check if the city name already exists or any other validation and if I ran into an Error or a Warning return it back to UI.
How can I pass any error/warning messages up to UI if my Ajax form expects to get back ajax true or false and whether that post was successful?
I would like to avoid using ViewData, ViewBags.
Thank you.
You can return any number of values in your JSON result, for example:
return Json(new { success = false, message = errorMessage });
And then interpret this on the client side. No need to use ViewData, ViewBags, etc. Just format the result on the client side, so you're just transmitting data over JSON.
EDIT:
I didn't realize you were using Ajax.BeginForm(). You should still be able to hook into the JSON results client side to parse the results. See How to use Ajax.BeginForm MVC helper with JSON result?.
Although I would suspect most people would use jQuery to accomplish the same thing, such as described on various StackOverflow posts like Darin's response at Using Ajax.BeginForm with ASP.NET MVC 3 Razor. Which is what I would recommend as well, since the jQuery library is very robust and cross platform tested.
I'm trying to implement the cascading dropdown from the toolkit. I need to get the count in a sub category dropdown, if it's zero then I turn off the visibility of the sub category.
If I use the javascript OnChange event then my script fires before the web method, so I need to know how to fire my script AFTER the web method has fired please.
My demo page: http://bit.ly/92RYvq
Below is my code and the order I need it to fire.
[WebMethod]
public CascadingDropDownNameValue[] GetSubCats1(string knownCategoryValues, string category)
{
StringDictionary kv = CascadingDropDown.ParseKnownCategoryValuesString(knownCategoryValues);
int CategoryID;
if (!kv.ContainsKey("Category") || !Int32.TryParse(kv["Category"], out CategoryID))
{
return null;
}
dsSubCat1TableAdapters.Categories_Sub1TableAdapter SubCats1Adapter = new dsSubCat1TableAdapters.Categories_Sub1TableAdapter();
dsSubCat1.Categories_Sub1DataTable SubCats1 = SubCats1Adapter.GetSubCats1(CategoryID);
List<CascadingDropDownNameValue> values = new List<CascadingDropDownNameValue>();
foreach (DataRow dr in SubCats1)
{
values.Add(new CascadingDropDownNameValue((string)dr["SubCategory1"], dr["SubCatID1"].ToString()));
}
return values.ToArray();
}
function getSubCatCount() {
$get("ddlSubCats1").style.display = $get("ddlSubCats1").length > 1 ? "block" : "none";
}
Generally when you call your web method function through javascript you can supply it two call back functions. One gets fired if there is an error and the other gets fire once the web method call has been completed. The callback requires two arguments, the result and a context. For example if your function was called myWebMethodFunction and your namespace it was contained in was my.fully.qualified.namespace it may look like this.
my.fully.qualified.namespace.myWebMethodFunction(param1, param2, ... , paramN, onErrorCallback, onCompleteCallback, context);
Once that function finishes, it will call the onCompleteCallback passing the result of your webmethod function and whatever you passed for a context.
It has been a while since I've called a web method function so I might have gotten the order of the callback reversed.
For some reason I can't comment on things either, but I can add to this.
I may be thinking about something different, but you must be calling something through javascript to fire your webmethod, correct? Whatever you use to call the webmethod through javascript should provide a mechanism to add a callback that will be fired once your webmethod call is complete and returned.
Use jQuery.ajax() it allows you to specify a success function and a failure function that fire after the web method returns.
If I want to call a server function from JavaScript to retrieve a name of a person from a database (just as an example)... and I went...
name = myServices.getName(userId);
If I have a script manager with a service reference to a .asmx file that has the web method getName( int userId ) {} then this function should be called properly and would, eventually, return the name for that userId.
Unfortunately, I want to do...
name = myServices.getName(userId);
alert(name);
however, when doing ASP.NET AJAX, it would call the web method and continue executing before waiting for a response from the server (which I understand is the point of AJAX, to stop the browser from freezing while waiting for data)
I need to get the name back from the server before I can continue executing... How can I approach this to fix this issue?
There is a method you can add as a parameter to the service method that will call the method on success where you can do other stuff.
For example:
function test() {
PageMethods.MyMethod("name", OnMyMethodComplete);
}
function OnMyMethodComplete(result, userContext, methodName) {
alert(result);
}
If you want to call a Web method synchronously, you'll need to set up the request manually and use a Sys.Net.XMLHttpSyncExecutor.
Here's an example (see ExecuteSynchronously function).
For a JavaScript solution, you could loop until name has a value. Adjust time-based on latency to keep app responsive
var time = 100;
window.setTimeout(name == '' ? wait : continue, time);
function wait() {
window.setTimeout(name == '' ? wait : continue, time);
}
function continue() {
//code having to do with name
alert(name);
}
Congratulations! You've taken your first step into a larger asynchronous world. I'd definitely go with using the callbacks that CSharpAtl suggested.