Is there much authentication overhead when WebAPI makes a request to the server? - asp.net

From what I understand. Every time a webapi request goes to the server then it's authenticated. My application uses WebAPI 2, Identity 2 and has get methods such as this:
/api/cityStatusList
/api/cityTypeList
/api/cityOptionList
These calls exist to get data for a page.
If the webapi is authenticating every request then should I look into how I can combine all these requests into one?

If the webapi is authenticating every request then should I look into how I can combine all these requests into one?
Why, is it causing any trouble?
You can of course define and return a class like this:
public class CityData
{
public List<CityStatus> StatusList { get; set; }
public List<CityType> TypeList { get; set; }
public List<CityOption> OptionList { get; set; }
}

Create CityView model class for your city like following :
public class CityView
{
public List<cityStatusView> cityStatusList { get; set; }
public List<cityTypeView> cityTypeList { get; set; }
public List<cityOptionView> cityOptionList { get; set; }
}
public class cityStatusView
{
public int ID { get; set; }
}
public class cityTypeView
{
public int ID { get; set; }
}
public class cityOptionView
{
public int ID { get; set; }
}
use it like following code in your web api :
// View model
var cityStatusList=..;
var cityTypeList=..;
var cityOptionList=..;
CityView objVM = new CityView();
objVM.cityStatusList = cityStatusList;
objVM.cityTypeList = cityTypeList;
objVM.cityOptionList = cityOptionList;
return ActionContext.Request.CreateResponse(HttpStatusCode.OK, objVM);

To address the question directly - yes, it is authenticating your application every time. However, on the scale of standard web-application this time is don't-you-even-worry-about-it miniscule.
Combining those routes into one might well be a good idea not because authentication has to happen multiple times, but because a web request can simply take a while. Typically this is due to the time it takes to physically send signals from the server to the client over TCP/IP (and re-send to compensate for any dropped packets). Even when parallelizing requests, fewer web requests is faster.
That being said, by default I would do the simplest thing possible and not worry about it. What I just mentioned is an optimization, should be treated as such, and not done prematurely.
As for authentication? It's just a few steps of the super-marathon that is your web request, it really doesn't matter. Someone correct me if I'm wrong, but I don't think it usually even hits the database - all it has to do is decode the claims that are stored in a cryptographically-secure fashion in the authentication cookie.

Related

Edit HTTP POST method to POST different data depending on existing data in .NET Core

I'm creating an API for a game that can (for now) only be played over Postman issuing POST and GET requests. It needs to be able to receive POST requests and update the InMemory database based on previous requests. Player state is not an issue - it just needs to allow for a player to issue a request and update a value based on the value of the previous request.
I have a Model that contains the class variables and automatically sets one of the variables to a PlayerScore value (0, initially).
public class Game
{
public long Id { get; set; }
public long PlayerScore { get; set; }
public bool Roll { get; set; }
public bool IsComplete { get; set; }
public Game()
{
this.PlayerScore = 0;
}
}
This sets the score to 0 every time the game is played/HTTP POST requests are submitted, but I want to be able to edit this value based on previous turns in the game.
Where should I place this method?
The POST is performed via an 'ActionResult' style method.
Thanks for any help anyone can possibly provide!
You seem to be using your Game class for both your internal game state and also the model from the POST request.
I'd recommend creating a separate class for your POST request so that they don't get confused. e.g.
public class GameUpdateRequest
{
public long Id { get; set; }
public long PlayerScore { get; set; }
public bool Roll { get; set; }
public bool IsComplete { get; set; }
}
// .. controller action
[HttpPost]
public IActionResult UpdateGame([FromBody] GameUpdateRequest request)
{
if (request.PlayerScore > 0)
// update game state logic
}
Then your request model can change and is not tied to the game state model. You could make PlayerScore nullable in the request or add other properties.

Rebus: Multiple sagas handling same message -OR- best practice for request/reply in saga

I have a scenario where I'm processing a message in a Saga and might need more information and thus send a request message for which I expect a reply.
The issue is that the reply does not have information unique to the current saga - it has an ID that I would like to use but multiple sagas might be requesting this ID at the same time and thus Rebus disallows it (exception: Correlation property 'Bla' has value '86' in existing saga data with ID 2d12a863-12ed-4632-82d8-290e041c4eed).
If there is no way to have a single message be handled by multiple sagas the alternative for me would be to be able to match the reply to the requesting saga. As far as I can tell there used to be support for this, but it was removed in a later version.
I've tried implementing this using the rbs2-corr-id header, and it works in my tests, however it feels like a hack.
Is there a better way to do it? Without modifying the messages?
I've considered using another saga to act as a sort of proxy by correlating on the ID that might be shared and having a list of correlation IDs for the original saga. I worry however that there might be concurrency issues causing the original saga to wait for the proxy saga.
The following code should show the problem:
public class Message
{
public Guid Id { get; set; }
public int OtherId { get; set; }
}
public class Request
{
public int OtherId { get; set; }
}
public class Response
{
public int OtherId { get; set; }
public string MissingInfo { get; set; }
}
public class SagaData : ISagaData
{
public Guid Id { get; set; }
public int Revision { get; set; }
public Guid MessageId { get; set; }
public int OtherId { get; set; }
}
public class MySaga : Saga<SagaData>, IAmInitiatedBy<Message>, IHandleMessages<Response>
{
IBus _bus;
public MySaga(IBus bus)
{
_bus = bus;
}
public async Task Handle(Message message)
{
Data.OtherId = message.OtherId;
// Send Request expecting someone to .Reply(new Response { OtherId = ,... })
await _bus.Send(new Request { OtherId = message.OtherId });
}
public async Task Handle(Response message)
{
// Do something with message.MissingInfo
}
protected override void CorrelateMessages(ICorrelationConfig<SagaData> config)
{
config.Correlate((Message m) => m.Id, s => s.MessageId);
// This works as long as only one saga has this ID
config.Correlate((Response m) => m.OtherId, s => s.OtherId);
}
}
I've tried implementing this using the rbs2-corr-id header, and it works in my tests, however it feels like a hack.
Well... it's a clever hack. 😅 I think this is actually the best you can do: Take advantage of the fact that the correlation ID of the request is under your control, and the reply will carry back the same correlation ID.
How about setting the correlation ID to the ID you'd prefer to see again, when you receive the reply?
And then you correlate your reply with something like
protected override void CorrelateMessages(ICorrelationConfig<InviteToTeamByEmail> config)
{
config.CorrelateHeader<YourReply>(Headers.CorrelationId, d => d.Bla);
}
(assuming that the name of the correlation property was actually Bla... 😆)

Ignore certain ViewModel properties in API requests?

Suppose I have the following example Resource Model defined for API Create/Read/Update/Delete interactions involving the Customer types:
public class CustomerModel
{
public string Address { get; set; }
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Url]
public Uri Website { get; set; }
public DateTimeOffset WhenCreated { get; set; }
public DateTimeOffset WhenUpdated { get; set; }
}
Id, WhenCreated, and WhenUpdated are metadata to be generated by the underlying data repository and as such, if the customer adds them to a request they should not be kept (Id for example, would be specified in the URL so no need to include in the request body). However, these values are still important to the client.
Is there a simple approach to ignoring these metadata attributes if sent in the client request? I would expect this in the form of an attribute but have not found anything promising for .NET Core 3.1.
The JsonIgnore attribute would make sense but it wouldn't serialize the values in responses either.
I could create a separate model only used by clients for requests but this seems redundant, especially because it will require new mapping profiles. However, if using something like Swashbuckle for API documentation this could be the best approach since the class documentation wouldn't represent those as valid properties for requests.
I could add some logic to remove those properties in the business logic layer but that would likely involve another request to the database to retrieve their original values so it isn't ideal.
Thank you!

How to design an internal Web Api using ASP.NET Web API

I am totally stuck. After searching for days, I finally decided to put my problem in front of you guys.
I need to develop a web api (using ASP.NET Web API 2) that would be used internally by a phone app and a web site. But I don't know how to design these specific cases:
1) Budget:
Budget Object:
public class Budget
{
public int Id { get; set; }
public string Name { get; set; }
public decimal TotalAmount { get; set; }
public decimal PendingAmount { get; set; }
public decimal ApprovedAmount { get; set; }
public decimal PaidAmount { get; set; }
public List<DepartmentBasicInfo> AvailableToDepartments { get; set; }
public string CurrencyCode { get; set; }
}
Budget Api controller:
public IHttpActionResult Get([FromUri]Models.BudgetModels.BudgetQueryModel query) {
return Ok(budgets);
}
The problem is all the Amount fields are calculated (not present in the database). The budgets need to return these when listed on the web page.
Then there are other web pages that would need a drop down list where it need to show budget name and currency and I do not want to calculate the budget amounts as this is a huge overhead in this case.
so the questions are:
1) As this is an internal web api, would this make sense to create two separate actions where one will return the whole Budget object and the other will return a thin Budget object (without Amounts and AvailableToDepartments properties) where calculations are not required, if yes what should be the route url?
2) Is there any clean way to able to use the same Budget class both for create and update in API because I am thnking that calculated fields do not belong to these operations.
3) Is it a good idea to pass a parameter to the Get method so it does not calculate budgets?
What is the cleanest way to handle these kind of cases? Please keep in mind that this is for an internal use api.
Thanks!
Iffi

ASP.NET Web API - Entity Framework - 500 Internal Server Error On .Include(param => param.field)

I am currently working on a Web API project with a Database-First method using Entity Framework (which I know is not the most stable of platforms yet), but I am running into something very strange.
When the GET method within my APIController tries to return all records in a DbSet with a LINQ Include() method involved such as this, it will return a 500 error:
// GET api/Casinos
public IEnumerable<casino> Getcasinos()
{
var casinos = db.casinos.Include(c => c.city).Include(c => c.state);
return casinos.AsEnumerable();
}
Yet, this method works fine, and returns my data from within my database:
// GET api/States
public IEnumerable<state> Getstates()
{
return db.states.AsEnumerable();
}
So I have proved in other instances that if it returns the entities without LINQ queries, it works great, yet when there is an Include method used upon the DbContext, it fails.
Of course, trying to find this error is impossible, even with Fiddler, Chrome/Firefox dev tools, and adding in GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
If anyone has resolved this, it would be nice to know a nice resolution so I can start returning my data! Thanks!:)
P.S. I am using SQL Server 2012
This is happening due to error in serialization (Json/XML). The problem is you are directly trying to transmit your Models over the wire. As an example, see this:
public class Casino
{
public int ID { get; set; }
public string Name { get; set; }
public virtual City City { get; set; }
}
public class State
{
public int ID { get; set; }
public string Name { get; set; }
[XmlIgnore]
[IgnoreDataMember]
public virtual ICollection<City> Cities { get; set; }
}
public class City
{
public int ID { get; set; }
public string Name { get; set; }
public virtual State State { get; set; }
[XmlIgnore]
[IgnoreDataMember]
public virtual ICollection<Casino> Casinos { get; set; }
}
public class Context : DbContext
{
public Context()
: base("Casino")
{
}
public DbSet<Casino> Casinos { get; set; }
public DbSet<State> States { get; set; }
public DbSet<City> Cities { get; set; }
}
Pay attention to the XmlIgnore and IgnoreDataMember. You need to restrict avoiding serialization so it doesn't happen in circular manner. Further, the above model will still not work because it has virtual. Remove virtual from everywhere namely City, Cities, Casinos and State and then it would work but that would be inefficient.
To sum up: Use DTOs and only send data that you really want to send instead of directly sending your models.
Hope this helps!
I had same problem in ASP.Net Core Web Api and made it working with this solution:
Add Microsoft.AspNetCore.Mvc.NewtonsoftJson nuget package to web api project.
and in Startup.cs class in ConfigureServices method add this code:
services.AddControllersWithViews().AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);

Resources