TypeScript with Angular.JS and web API - asp.net-mvc

I'm working on an asp.mvc3 web api project. in this project I use TypeScript and Angular.js
and I need to access the business layer from TypeScript through the Web API. I called the Web API inside the constructor method in TypeScript using the
code given below.
constructor($scope, $http: any) {
$scope.VM = this;
$http.get("/API/PrivateAPI/Test/1").success((a) => { this.Tiles = a });
var bb = this.Tiles;
}
However, when trying to get the object list from the business layer, the Tiles array is empty. I debugged the code and found out the Web API is called after passing the last line of the constructor and does return results. I need to call that method inside the constructor and get object list to the Tiles array.
Does anyone know how to do so?

First of, I think you should do the following (notice .data) :
$http.get("/API/PrivateAPI/Test/1").success((response) => { this.Tiles = response.data });
Anyways, $http only supports async http requests. What you want can be done by a synchronous XHR request and that is considered bad UI experience, since the browser window freezes till the XHR request completes, and therefore $http doesn't support it (configuration docs).
What you can do is something like :
call another function from response e.g.
(response) => { this.Tiles = response.data; this.continueWithProcessing(); }
Or, Setup a variable to hide a preloader when the response comes back:
(response) => { this.Tiles = response.data; this.allDone=true; }
Where you have an ng-show on something like:
<div ng-show="!VM.allDone">Loading the data....</div>
Or both :)
Note: An async setting is supported in underlying browsers native XHR object and therefore in $.ajax which is the jquery ajax function : http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings. However it is a horrible UI experience + if you use it from angular you are responsible for scope.apply.

Related

jQuery axax lifecycle and response in ASP.NET MVC application or API in general

I need a clarification on jQuery Ajax lifecycle when calling an endpoint, in my specific case an ASP.NET MVC (Net core/Net 5) application.
What I specifically need is to know how the success/error event chain works and when exactly the control is returned to jquery once the http call is fired.
Let's imagine a jquery ajax like this
postData = JSON.stringify({test: 1, anotherVariable : "YEEEE"});
$.ajax({
url: '#Url.Action("MyAspNetAction", "MyAspNetController")',
type: "POST",
contentType: 'application/json; charset=utf-8',
dataType: "json",
data: postData,
success: function (result) {
showMessage(result.responseText, result.success ? 'success' : 'error', 3000)
},
error: function (error) {
showMessage(result.responseText, 'success', 3000)
}
});
On the server I have an async Task controller which we could define as:
public async Task<JsonResult> MyAspNetAction([FromBody] MyAspNetActionModel){
try{
await someLongAction();
return some jsonresult { success = true, responseText = "HELLO"}
}
catch(Exception ex)
{
return some jsonresult { success = false, responseText = "ERROR"}
}
}
which gets executed async from asp net (I guess).
Now, Let's suppose I do various risky task in this action, like manipulating
HttpContext.Session["key"]
ViewData["Key"]
calls to other async stuff which takes some time to get executed (let's say 30 seconds for the sake of putting up a worst-case scenario.
All this togheter.
Now,
WHEN javascript gets control back and WHEN SUCCESS???
Am I handling this right?
I mean, all that async stuff is happening (ajax async, mvc action is async and so on.
Will the jquery action go to succes only after my MVC action is completed and gets the result?
Or the mere fact that jquery ajax managed to call my action will result in a HTTP 200 (so it's ok/success) and it will ignore all the code called inside, which has to be handled in another way, and the following javascript will be executed?
Basically I want to know if I can execute all the code in the MVC action being sure that ajax will enter in succes/error only when the action completed all the code
AND
if the javascript following the jquery ajax will continue executing and the control to the ajax action will return later
The client and the server on an HTTP request work independently.
The client issues a request.
The server handles the request and sends the response.
The client receives the response.
Each end can be running on any architecture and, if possible, the client can block during 2 or asynchronously await for 3 during 2.
The server (2) can be synchronous or asynchronous, but it sequentially does:
Receive the request.
Handle the request.
Send the response.
Regarding ASP.NET, you should not be concurrently messing with HTTP-related components or view components.
Your action method should:
Collect data from HTTP (model binding and other data).
Call any model/services needed to handle the request.
Produce the response (View, or any other response type).

Returning result for .net Web Api from db call

I'm new to the .net Web API and am trying to figure out how I return a Get result from a call to my database. I know everything works in my regular MVC page. But Not sure how to return the result from the Web API controller. I thought it was as simple as returning Json with the result. Here is my code:
// GET api/<controller>
public IEnumerable<string> Get()
{
using (var _db = new JobsDatabaseEntities())
{
var user = Env.CurrentUser;
var posts =
_db.JobPostings.Where(
j =>
j.City.Equals(user.City, StringComparison.OrdinalIgnoreCase) &&
j.Industry.ID == user.Industry.ID);
var result = new List<BusJobPost>();
foreach (var post in posts)
{
var p = new BusJobPost(post);
result.Add(p);
}
return Json(result);
}
}
Please visit this resource: Action Results in Web API 2. Your case is described in fourth section Some other type (which is applicable to first version of Web API as well).
In Web API you don't return JSON result explicitly. It is actually done by process called Content Negotiation. You can read about it here [Content Negotiation in ASP.NET Web API] in detail.
Highlighting briefly just some of this:
You can set Accept header for you request as: Accept: application/json (for example, if you use jquery ajax function: dataType: 'json')
Or even if you don't use Accept header at all, if you send request with JSON data, you should also get response back in JSON format
So you should just return result variable from your controller action and satisfy some of conditions to get response serialized into JSON.

MiniProfiler and AngularJS

Recently I was trying to profile ASP MVC methods called with AngularJS $http service and I noticed that MiniProfiler does not update the data as it does for AJAX calls from JQuery, for example.
Is there a way to use MiniProfiler with Angular ?
Adjustment needed for Angular (1.3.10)
(not needed if you are using another library for your XHR-needs)
MiniProfiler does this to XMLHttpRequest to be able to intercept all XHR-calls for angular
XMLHttpRequest.prototype.send = function sendReplacement(data) {
if (this.onreadystatechange) {
...
Well, Angular never sets xhr.onreadystatechange so we need to adjust this in a harmless way:
function createXhr() {
var xhr = new window.XMLHttpRequest();
xhr.onreadystatechange = function () { };
return xhr;
}
Explained in detail here
This issue was addressed with this pull request and has been fixed in the current MiniProfiler nuger.

Redirecting from an API

I am trying to learn/expand my knowledge of .NET MVC/REST/API's and Web-sockets/SignalR. To do this I am implementing a chat app.
I have a typical MVC intro page that gets the users name and email address in a form and that data is submitted to a RESTFul API where the new user is added to the database.
<form class="form-horizontal" role="form" action="/api/GroopsAPIUsers" method="POST">
Inside of the controller for that page(?) I'm redirecting the user to a page where they can select which room they would like to enter.
public HttpResponseMessage Post( GroopsUser userValue)
{
userValue.ID = Guid.NewGuid();
bool results = groopsRepository.AddNewUser(userValue);
// return results;
var response = Request.CreateResponse(HttpStatusCode.Redirect);
//from http://stackoverflow.com/questions/11324711/redirect-from-asp-net-web-api-post-action
string fullyQualifiedUrl = Request.RequestUri.GetLeftPart(UriPartial.Authority);
response.Headers.Location = new Uri (fullyQualifiedUrl + "/home/rooms/?userID=" + userValue.ID);
return response;
}
But this doesn't feel right. It seems like the API should only be doing CRUD operations and shouldn't have anything to do with which page the user is redirected to.
Is this the wrong approach?
If so, can someone point me in the right direction?
(I'm not sure that I've used all of these terms correctly)
...gregory
I can see why you don't think it feels right. Usually, you would design your Web API in such a way, that it is platform agnostic, so the only thing it cares about is the incoming HTTP requests, and operations based on those. When you redirect a request to another URL, you are designing around the web browser, thus constraining yourself to that one platform. Sometimes that's what you need, sometimes it isn't.
(if it indeed is what you need, then you should probably stick to just regular Asp.NET MVC, and not Web Api)
Instead of what you have now, you could make your application more flexible by returning, for example, a 200 status code from your controller, after a successful operation. That way, it is up to the client-side application to decide what to do from there. (This is where you redirect, if your client-side application is browser-based.)
So how exactly do you achieve this with your browser application? You might already have guessed it, but the answer is Javascript. Instead of making a synchronous POST request to your API, via your form, you could make the request async, and then wait for the response from the server. Then you can take an appropriate action, based on what the response contains.
A quick example:
Controller
public HttpResponseMessage Post(GroopsUser userValue)
{
userValue.ID = Guid.NewGuid();
bool results = groopsRepository.AddNewUser(userValue);
var response = Request.CreateResponse<GroopsUser>(HttpStatusCode.OK, userValue);
return response;
}
Form
<form class="form-horizontal" id="group-form" onsubmit="return addToGroup()" role="form" action="/api/GroopsAPIUsers" method="POST">
Javascript (jQuery)
<script>
function addToGroup()
{
$.ajax({
type: "POST",
url: $('#group-form').attr('action'),
data: $('#group-form').serialize(),
dataType: "json",
success: function(data) {
window.location.replace('/home/rooms/?userID=' + data.ID);
},
error: function(){
alert('error handing here');
}
});
return false;
}
</script>
If anything is unclear, or if I'm mistaken about anything, please let me know!
It depends on what you are doing with said API. You can setup an API to perform purely CRUD operations or you can make your API a lot smarter and say have it serve up actual HTML to be rendered on the client (which is sort of what MVC does) or you can take it a step further and turn it into a Hypermedia service that will define the view as well as the state of your system. The front end is then tasked with simply rendering what is provided by your API.

Help with Ajax post to action method

I am a new to MVC an need a little help.
In my view I make an ajax post as below.
function PostCheckedPdf(e) {
var values = new Array();
$('input:checked').each(function () { values.push(this.value); });
$.post("/UnregisteredUserPreview/DownloadPdfInvoice",
{ checkedList: values });
}
This post the values of any checkboxes that are checked inside a third party Grid component (Telerik). The Action method receives the array fine and loops through each value rendering a pdf report and putting the report into a ZipStream which is attached to the Response. After the loop the zipstream is closed and I return View();
When the Action is invoked through the $.post it runs through the action method but nothing happens in the browser.
If I call the Action through an action link (with a couple of hard coded value instead of passing the checked boxes values) the zip file with all the pdfs is downloaded.
What am I doing wrong or how can I post the checked values with an ActionLink?
Thanks in Advance!
Toby.
The difference is that your ActionLink is emitting an <a> tag, which is performing a GET operation. The browser interprets the contents of the response and opens the PDF.
Your jQuery method is performing a POST, but does nothing with the response, and thus silently throws it away in the background.
You need to actually do something with the return contents, like write it out to another window.
var w = window.open('', '', 'width=800,height=600,resizeable,scrollbars');
$.post("/UnregisteredUserPreview/DownloadPdfInvoice",
{ checkedList: values },
function(content){
w.document.write(content);
w.document.close(); // needed for chrome and safari
});
You are making an Ajax call to the server there and client side code should receive the returned result which seems that you are not doing there. It should be something like below :
$.ajax({
type: 'POST'
url: '/UnregisteredUserPreview/DownloadPdfInvoice',
data: { checkedList: values },
success: function (r) {
alert(r.result);
}
});
And assume that your controller is like below :
public ActionResult DownloadPdfInvoice() {
//do you stuff here
return Json(new { result = "url_of_your_created_pdf_might_be_the_return_result_here"});
}
NOTE
If you are posting your data with anchor tag, it is better to
prevent the default action of this tag so that it won't do anything
else but the thing you're telling it to do. You can do that by adding the
following code at the end of your click event function :
$("#myLink").click(function(e) {
//do the logic here
//ajax call, etc.
e.preventDefault();
});
Have a look at the below blog post as well. It might widen your thoughts :
http://www.tugberkugurlu.com/archive/working-with-jquery-ajax-api-on-asp-net-mvc-3-0-power-of-json-jquery-and-asp-net-mvc-partial-views

Resources