Update clients in asp.net core 2.0 using SignalR - asp.net-web-api

I am going through several examples on Asp.net Core WebAPI with SignalR where most of them are demonstrating simple chat application where this is what Hub returns:
return Clients.All.InvokeAsync("Send", message);
And this is how it gets called in Startup.cs
routes.MapHub<Chat>("chat");
The above example is good if message is not be send and updated to all the clients. In my case I have several APIs to be called whenever a data is changed:
Like Bank Transaction is done, I have to update ledger and several other reports at client side. But I don't see any option to pass Json.
Not finding exactly how to do this so that WebAPI gets refreshed everytime a change is there in the database.
As far as I understood, here "chat" is the endpoint which will be called from the frontend.
In this case what will happen to the endpoint I have created so far. Have a look at the below code example:
This api is to be called every time an entry is done:
public async Task<object> GetMarket(string marketshortcode)
{
Markets market = new Markets(marketshortcode);
return market.GetMarket();
}
and this the entry:
[Authorize]
[HttpPost]
public async Task<object> sellCurUser([FromBody] SellCur model)
{
if (model != null)
{
SellCurUser suser = new SellCurUser();
suser.sellcur = model;
my addition code...
}
return ....
}
There are several more endpoints which needs to be called at certain update/creation.
Now the point is how these apis will be changed or even not changed at all.
Do anyone have any example to understand it simply.

Related

Web API - Handling the long running call when aggregating the calls

I have a web api project which works as a GateWay for other Mobile clients. When the mobile client makes a call to this Gateway it internally calls the existing services which are hosted by another project and it aggregates the results and return to the client. I have recently come across a situation when my gateway is internally making 3 calls first 2 are returning the data fast but the 3rd call is taking lot of time I want to know the best way to handle this scenario.
Ensure that the return type of API action methods is async Task<YourModelDataType>.
For example, let's say you have a HomeController controller as follows:
public class HomeController : ApiController
{
public async Task<YourModelDataType> Index()
{
return new YourModelDataType()
{
Property1 = await ApiService1.GetData(),
Property2 = await ApiService2.GetData(),
Property3 = await ApiService3.GetData(),
};
}
}
Ensure that calls to the other API projects are awaited. This improves scalability on the server side. i.e. server resources are free to serve other requests while awaiting response from other API services.

ASP.net Core RC2 Web API POST - When to use Create, CreatedAtAction, vs. CreatedAtRoute?

What are the fundamental differences of those functions? All I know is all three result in a 201, which is appropriate for a successful POST request.
I only follow examples I see online, but they don't really explain why they're doing what they're doing.
We're supposed to provide a name for our GET (1 record by id):
[HttpGet("{id}", Name="MyStuff")]
public async Task<IActionResult> GetAsync(int id)
{
return new ObjectResult(new MyStuff(id));
}
What is the purpose of naming this get function, besides that it's "probably" required for the POST function below:
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return CreatedAtRoute("MyStuff", new { id = myStuff.Id }, myStuff);
}
I notice that CreatedAtRoute also has an overload that does not take in the route name.
There is also CreatedAtAction that takes in similar parameters. Why does this variant exist?
There is also Created which expects a URL and the object we want to return. Can I just use this variant and provide a bogus URL and return the object I want and get it done and over with?
I'm not sure why there are so many variants just to be able to return a 201 to the client. In most cases, all I want to do is to return the "app-assigned" (most likely from a database) unique id or a version of my entity that has minimal information.
I think that ultimately, a 201 response "should" create a location header which has the URL of the newly-created resource, which I believe all 3 and their overloads end up doing. Why should I always return a location header? My JavaScript clients, native mobile, and desktop apps never use it. If I issue an HTTP POST, for example, to create billing statements and send them out to users, what would such a location URL be? (My apologies for not digging deeper into the history of the Internet to find an answer for this.)
Why create names for actions and routes? What's the difference between action names and route names?
I'm confused about this, so I resorted to returning the Ok(), which returns 200, which is inappropriate for POST.
There's a few different questions here which should probably be split out, but I think this covers the bulk of your issues.
Why create names for actions and routes? What's the difference between action names and route names?
First of all, actions and routes are very different.
An Action lives on a controller. A route specifies a complete end point that consists of a Controller, and Action and potentially additional other route parameters.
You can give a name to a route, which allows you to reference it in your application. for example
routes.MapRoute(
name: "MyRouteName",
url: "SomePrefix/{action}/{id}",
defaults: new { controller = "Section", action = "Index" }
);
The reason for action names are covered in this question: Purpose of ActionName
It allows you to start your action with a number or include any character that .net does not allow in an identifier. - The most common reason is it allows you have two Actions with the same signature (see the GET/POST Delete actions of any scaffolded controller)
What are the fundamental differences of those functions?
These 3 functions all perform essentially the same function - returning a 201 Created response, with a Location header pointing to the url for the newly created response, and the object itself in the body. The url should be the url at which a GET request would return the object url. This would be considered the 'Correct' behaviour in a RESTful system.
For the example Post code in your question, you would actually want to use CreatedAtAction.
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return CreatedAtAction("MyStuff", new { id = myStuff.Id }, myStuff);
}
Assuming you have the default route configured, this will add a Location header pointing to the MyStuff action on the same controller.
If you wanted the location url to point to a specific route (as we defined earlier, you could use e.g.
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return CreatedAtRoute("MyRouteName", new { id = myStuff.Id }, myStuff);
}
Can I just use this variant and provide a bogus URL and return the object I want and get it done and over with?
If you really don't want to use a CreatedResult, you can use a simple StatusCodeResult, which will return a 201, without the Location Header or body.
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return StatusCode(201);
}
I believe there is an example for you here.
Remembering that I'm using .NET 6
[HttpPost]
public IActionResult CadastrarCerveja([FromBody] Cerveja cerveja)
{
using (var ctx = new CervejaContext())
{
ctx.Cervejas.Add(cerveja);
ctx.SaveChanges();
}
return CreatedAtAction(
nameof(LerCerveja),
new { IdCerveja = cerveja.Id },
cerveja);
}
[HttpGet("{IdCerveja}")]
public IActionResult LerCerveja(int IdCerveja)
{
var ctx = new CervejaContext();
var cerv = ctx.Cervejas.FirstOrDefault(c => c.Id == IdCerveja);
if (cerv == null)
return NotFound();
else
return Ok(cerv);
}

Web API 2 - Unity IOC - Shared instance per request variable

I am using web api with unity IOC.
web api client passes client-id in request header and based on this value dependencies are resolved to create a external dll's method instance.
creation of this instance take around 6-7 seconds which is creating performance issues in web api.
What I want is to prevent instance creation for call with same client-id in header.
This is how I have implemented till now:-
//========================== ArchiveFactory ==========================
ArchiveFactory archiverFactory = (HttpRequest httpRequest) =>
{
container.RegisterType<IArchive, Archive>("Archive",
new HierarchicalLifetimeManager(),
new InjectionConstructor(
new ResolvedParameter<IStoreClient>(),
Helper.GetArchiveContext(httpRequest))
);
return container.Resolve<IArchive>("Archive");
};
container.RegisterInstance(archiverFactory);
To be specific in my requirement - I am calling amazon services to retrieve images and there is a corporate dll which invokes amazon.
You can use caching mechanism at the controller/API layer(e.g Strathweb.CacheOutput.WebApi2) and you can decorate the controller method like this below. It's can cache based on parameter so if request comes in with same parameter, it will return results from cache.
[HttpGet]
[Route("")]
[CacheOutput(ServerTimeSpan = 60, ExcludeQueryStringFromCacheKey = true)]
public IHttpActionResult GetProducts(string clientId)
{
var product = new List<Product>();
return Ok(product);
}
Also, you might want to check the class constructor that you are trying to instantiate for issues that is taking it too slow. You may want to consider using lazy loading too if that will apply.

How to delay the response of my Web API

I am working on a Web API project and that has an Artist Web API Controller. On there, there is the api/artist method that is a GET for all artists.
When making the call to this method, I would like a 3 second delay before I serve the data, how can I achieve this?
CODE
public class ArtistController : ApiController
{
private GlContext db = new GlContext();
// GET api/Artist
public IQueryable<Artist> GetArtists()
{
return db.Artists;
}
}
I know that you wouldn't want to do this in a production environment, but I am playing with preloaders, and in order to test them properly I need to introduce this delay.
If it is just for testing you can always go for Thread.Sleep(3000)
http://msdn.microsoft.com/en-us/library/d00bd51t%28v=vs.110%29.aspx

How to apply single page application functionality on parts of asp.NET MVC3 projects?

So I'm creating a asp.NET MVC3 application and want to apply single page application functionality to parts of the application. I think the easiest way to explain is with an example:
The app consists of an admin area and a public area and is built using ordinary link-structure. I want to convert the admin area to an single page application reusing view and models from the existing application. Is it possible to do this and in that case how?
You have to face two main problems, which makes the difference between SPA and standard application:
Links: In standard application, each link redirects you to a different page.
Forms: When a form is been submitted, a request is been issued with the HTTP method you've specified in the post (usually POST) and it contains in the payload the data the user has entered.
In order to solve that problems, you have to take action both in client-side and server-side.
For explaining propose, lets take the following code:
HomeController.cs:
public class HomeController : Controller {
public ActionResult Index() {
return View();
}
public ActionResult Contact() {
return View(new ContactUsViewModel());
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Contact(ContactUsViewModel model) {
if (ModelState.IsValid) {
/* Send mail / Save in DB etc. */
return Redirect("Index");
}
return View(model);
}
}
Index.cshtml:
<p>This is a simple page.</p>
<p>#Html.ActionLink("Click here to contact us", "Contact")
Client-Side:
We should fix up linking between pages, as well as forms submittions.
Links: You can wire up an event in JS (jQuery if you'd like) that'll observe for each link click in the areas you'd like to apply on SPA - then, instead of redirecting the user - you'll load the content via AJAX.
For instance, take a look at this sample:
$("a").click(function(e) {
e.preventDefault(); // Disable standard redirecting
var href = $(e.currentTarget).attr("href");
$.get(href, function(responseText) {
$("#main-content-wrapper").html(responseText);
});
});
Forms: Just like in the approch we've used for links, we can wire up an observer to the form submit event in JS and then transfer the data using AJAX.
For instance:
$("form").submit(function(e) {
e.preventDefault(); // Disable standard submittion
var data = $(e.currentTarget).serialize(); // Serializing the form data
var method = $(e.currentTarget).attr("method");
if (typeof (method) == "undefined") { method = "POST"; }
$.ajax({
method: $(e.currentTarget).attr("method"),
parameters: data,
statusCodes: {
404: function() { /* Handle it somehow */ }
403: function() { /* Handle it... */ }
200: function(response) {
/* Since we've done a form submittion, usurally if we're getting standard OK (200) status code - we've transffered a data - such as JSON data - indicating if the request success or we got errors etc. The code you're writing here depends on how your current application works. */
},
});
});
Server-Side:
Since you don't wish to break your current application logic - you have to still be able to use standard ASP.NET MVC methods - such as View(), Redirect() and so on.
In this case, I recommend to create your own custom base Controller class - which will override ASP.NET basic implementation.
For instance, this is a starting point:
public class MyController : System.Web.Mvc.Controller {
public override View(string viewName) {
if (Request.IsAjaxRequest()) {
return PartialView(viewName); // If this is an AJAX request, we must return a PartialView.
}
return base.View(viewName);
}
}
Few things you have to keep in mind:
You have to somehow distinguish between standard requests and AJAX requests - the way I've used with Request.IsAjaxRequest() is a great way to do so.
Many times when you're handling a form, In the form submittion action, after you finish with the form logic, you're using Redirect() to redirect the user to another page. As you may have guessed, you can't take this approch when developing SPA. However, I can think of few solutions for this problem:
You can create a status handler in the JS code so when redirecting is been issued by the server - you can load the content via AJAX / display a message and so on.
You can override Redirect() and add a specific logic to perform in case of redirection when the request was done by AJAX - for instance, you can request from ASP.NET to perform the action that you're going to be transfered into and then return its content etc.
You can decide that although its an SPA app - when a redirect was issued - you allows the server to perform this redirection.
As you can see - there're many approches you can take, and they depends on the way you've developed your site, how you wish it to work and what is the basic rules you're defining (e.g. "No redirection is permitted never - even after submitting a form", "After form submittion - always in case that the operation success - I'm displaying a message or performing other JS action. Because of that, I can override Redirect() and if this is an AJAX request I can return a JSON object." etc.)

Resources