This type T gives even more reusability to the RepositoryBase class. 13.1.1 Validating Int Type Lets create one more request with the request body without the age property: https://localhost:5001/api/companies/53a1237a-3ed3-4462-b9f0-5a7bb1056a33/employees We can clearly see that the age property hasnt been sent, but in the response body, we dont see the error message for the age property next to other error messages. ASP.NET Core validates the model object as soon as the request gets to the action. If we add the fact that I got access to the private community and even more content by purchasing the Premium edition, buying this package has been an excellent choice. Once we send our request, the rules defined by Data Annotation attributes are checked. Why? "op": "remove", "path": "/name" Sets a default value to a required property. 131 Using the await keyword is not mandatory, though. }.ToString()); } }); }); } } In the code above, weve created an extension method in which weve registered the UseExceptionHandler middleware. For that, lets open the api/authentication/login action, click try it out, add credentials, and copy the received token: 272 Once we have copied the token, we are going to click on the authorization button for the /api/companies request, paste it with the Bearer in front of it, and click Authorize: 273 After authorization, we are going to click on the Close button and try our request: And we get our response. Thats because the private cache is stored in the browser and another client will hit the API for the same response. By default, a document named swagger.json is generated by the Swagger 266 tool which is based on our API. ; database=CompanyEmployee; Integrated Security=true" }, "AllowedHosts": "*" } It is quite important to have the JSON object with the ConnectionStrings name in our appsettings.json file, and soon you will see why. Inside the Repository project, we are going to create an abstract class RepositoryBase which is going to implement the IRepositoryBase interface. Finally, the PATCH method is neither safe nor idempotent. Build a fully data-driven REST Web API using cutting-edge technology; Troubleshooting and debugging errors along with implementing best practices and writing efficient logic Inside the logs folder, you should find a file with the following logs: Thats all we need to do to configure our logger for now. For the disallowed requests, we use a 429 status code; that stands for too many requests. In the method body, we can now await the GetAllCompaniesAsync() method. To do that, lets find the CompanyEmployees.xml file in the main project, right-click on it, and choose Properties . Then in the LoggerService project, right-click on Dependencies and choose the AddReference option. Since we have referenced the Contracts project through the LoggerService , it will be available in the main project too. After the console appears, type: Install-Package NLog.Extensions.Logging -Version 1.6.5 After a couple of seconds, NLog is up and running in our application. If we take a look at our launchSettings.json file, we are going to see that this variable is currently set to Development . We need them to be able to check if the field received through the query string exists in the Employee class: var propertyInfos = typeof(Employee).GetProperties(BindingFlags.Public | BindingFlags.Instance); That prepared, we can actually run through all the parameters and check for their existence: if (string.IsNullOrWhiteSpace(param)) continue; var propertyFromQueryName = param.Split(" ")[0]; var objectProperty = propertyInfos.FirstOrDefault(pi => pi.Name.Equals(propertyFromQueryName, StringComparison.InvariantCultureIgnoreCase)); 176 If we dont find such a property, we skip the step in the foreach loop and go to the next parameter in the list: if (objectProperty == null) continue; If we do find the property, we return it and additionally check if our parameter contains desc at the end of the string. A complete, hands-on, and easy to digest program that gets you from zero to building production-ready APIs in just a few. A complete, hands-on, and easy to digest program that gets you from zero to building production-ready APIs in just a few weeks. Author: Marinko Spasojevic, Vladimir Pecanac: Year: 2021: Format: PDF: Pages: 288: Views: 3232: #aspnet #netcore #webapi #backend. The Core Common Language Runtime for .NET Core is booted to host the app in the worker process. It is a dictionary containing the state of the model and model binding validation. We are going to explain step by step how to integrate Identity in the existing project and then how to implement JWT for the authentication and authorization actions. We should deploy our application to the staging environment as soon as we start building it. After that, we create an array of type object ( objectArray ) that consist of all the GUID values we sent to the API and then create an array of GUID types (guidArray ), copy all the values from the objectArray to the guidArray , and assign it to the bindingContext . We are accepting the JsonPatchDocument from the request body. Now, we have to register the filter in the ConfigureServices method: services.AddScoped(); And to decorate the GetEmployeesForCompany action: [HttpGet] [ServiceFilter(typeof(ValidateMediaTypeAttribute))] public async Task GetEmployeesForCompany(Guid companyId, [FromQuery] EmployeeParameters employeeParameters) Great job. So, having the proper documentation for our API enables consumers to integrate our APIs as quickly as possible and move forward with their development. We are going to show you how to do this. If we inspect the GetEmployeesForCompany action in the EmployeesController , we can see that we return all the employees for the single company. That is because the age is of type int and if we dont send that property, it would be set to a default value, which is 0. Once we transfer our database model to the real database, we are going to see how all these validation attributes and navigational properties affect the column definitions. We are not collecting it from the URI but from the request body. About the book ASP.NET Core in Action, Second Edition is a comprehensive guide to creating web applications with ASP.NET Core 5.0 . 167 What we want to achieve is something like this: https://localhost:5001/api/companies/companyId/employees?se archTerm=Mihael Fins This should return just one result: Mihael Fins. Lets continue with child resources creation. Notice how we use the ExpandoObject as a return type. Do the same thing for the second project and name it LoggerService . What if we try to send a remove operation, but for the valid path: 124 We can see it passes, but this is not good. In this case, that will be appsettings.Production.json . With all of this in mind, we can start with the Get requests. By inheriting from the RepositoryBase class, they will have access to all the methods from it. For example, you can send a date value to request an employee, but you wont have much success. All the changes will be applied or if something fails, all the changes will be reverted: _repository.Company.Create(company); _repository.Company.Create(anotherCompany); _repository.Employee.Update(employee); _repository.Employee.Update(anotherEmployee); _repository.Company.Delete(oldCompany); _repository.Save(); 43 After these changes, we need to register our manager class and add a reference from the Repository to our main project if not already done so. The first thing we are going to do is add an extension method in the ServiceExtensions class: public static void ConfigureResponseCaching(this IServiceCollection services) => services.AddResponseCaching(); We register response caching in the IOC container, and now we have to call this method in the ConfigureServices method: services.ConfigureResponseCaching(); Additionally, we have to add caching to the application middleware in the Configure method right above UseRouting() : app.UseResponseCaching(); app.UseRouting(); Now, we can start our application and send the same GetCompany request. This ensures we dont get a 406 Not Acceptable response. The main goal of caching is to eliminate the need to send requests towards the API in many cases and also to send full responses in other cases. To create a new project, right-click on the solution window, choose Add and then NewProject. This will put your newly learned skills to practical use and impress your boss and coworkers. When we implement some breaking changes, we want to ensure that we dont do anything that will cause our API consumers to change their code. Async programming is a parallel programming technique that allows the working process to run separately from the main application thread. Ultimate asp.net core 3 web api pdf Jobs, Employment | Freelancer There's also live online events, interactive content, certification prep materials, and more. Lets say we want to find out which employees are between the ages of 26 and 29. All we do is to set the state of the company to Added. The first thing we are going to do is extend the CompanyForCreationDto class: public class CompanyForCreationDto { public string Name { get; set; } public string Address { get; set; } public string Country { get; set; } public IEnumerable Employees { get; set; } } We are not going to change the action logic inside the controller nor the repository logic; everything is great there. Lets create a new class in the DataTransferObjects folder: public abstract class EmployeeForManipulationDto { [Required(ErrorMessage = "Employee name is a required field.")] But if code isn't clean, it can bring a development organization , by Now, we have to provide to IIS the name of that key and the value as well. It lives on the network. But debugging in a production environment is not that easy. This course will help you build a fully data-driven REST web API using cutting-edge technology. Weve just changed the return type and added the async keyword to the method signature. "); return BadRequest("Company collection is null"); } var companyEntities = _mapper.Map(companyCollection); foreach (var company in companyEntities) { _repository.Company.CreateCompany(company); } _repository.Save(); var companyCollectionToReturn = _mapper.Map(companyEntities); var ids = string.Join(",", companyCollectionToReturn.Select(c => c.Id)); return CreatedAtRoute("CompanyCollection", new { ids }, companyCollectionToReturn); } So, we check if our collection is null and if it is, we return a bad request. 6 Best ASP.NET Books for 2022 [Learn ASP.NET Core ASAP] - RealToughCandy Our website and the application pool should be started automatically. Its an open standard and its a popular mechanism for web authentication. The WriteResponseBodyAsync method constructs the response. 26 We are going to define all these constants in a text file in the main project and name it nlog.config . If we take a look at our mapping code in the GetCompanies action, we can see that we manually map all the properties. 41 It is quite common for the API to return a response that consists of data from multiple resources; for example, all the companies and just some employees older than 30. We also want to constrain our API not to return all the employees even if someone calls https://localhost:5001/api/companies/companyId/employees . This course also features web API development; the ability to design and maintain an API is an important toolset for the modern web developer. The first is modifying the filter logic and the second is adding the Search method for the searching functionality. It does that by collecting information from the private methods and serializing token options with the WriteToken method. The installed library will provide that for us. Ultimate ASP NET Core 3 Web API API . So, lets modify the IEmployeeRepository interface: public interface IEmployeeRepository { IEnumerable GetEmployees(Guid companyId, bool trackChanges); Employee GetEmployee(Guid companyId, Guid id, bool trackChanges); void CreateEmployeeForCompany(Guid companyId, Employee employee); void DeleteEmployee(Employee employee); } The next step for us is to modify the EmployeeRepository class: public void DeleteEmployee(Employee employee) { Delete(employee); } Finally, we can add a delete action to the controller class: [HttpDelete("{id}")] public IActionResult DeleteEmployeeForCompany(Guid companyId, Guid id) { var company = _repository.Company.GetCompany(companyId, trackChanges: false); if(company == null) { _logger.LogInfo($"Company with id: {companyId} doesn't exist in the database. But it is quite normal to create a collection of resources, and in this section that is something we are going to work with. RepositoryContext.Set() .AsNoTracking() : RepositoryContext.Set(); public IQueryable FindByCondition(Expression expression, bool trackChanges) => !trackChanges ? This means that the server made an error, which is not the case. Code Maze is an excellent place for getting the latest best practices related to the web development world. As a result, we can see 204 , which means that the entity has been updated. I cant even imagine the hours that would need to be spent to get all of this information. Everything works well. And if you want to have expiration and validation, you should combine them with the Marvin library and you are good to go. If youve checked Configure for HTTPS checkbox earlier in the setup phase, you will end up with two URLs in the applicationUrl section one for HTTP, and one for HTTPS. Right click on your Main project ThirdPartyAPIExample and select Add >> New Item.An "Add New Item" dialog box will open. We can confirm that from the migration file: 98 So, all we have to do is to create a logic for deleting the parent resource. If we navigate to the GetConnectionString method definition, we will see that it is an extension method that uses the ConnectionStrings name from the appsettings.json file to fetch the connection string by the provided key: 34 Afterward, in the Startup class in the ConfigureServices method, we are going to add the context service to the IOC right above the services.AddControllers() line: services.ConfigureSqlContext(Configuration); Migration is a standard process of creating and updating the database from our application. So, we shouldnt choose the noun products or orders when we work with the companies resource; the noun should always be companies. The specific approach we utilize is also known as the Constructor Injection . You can upgrade your tier to the higher one at the reduced price. true : false; var companyId = (Guid)context.ActionArguments["companyId"]; var company = await _repository.Company.GetCompanyAsync(companyId, false); if (company == null) { _logger.LogInfo($"Company with id: {companyId} doesn't exist in the database. As you can see, we have three checks in our code and they are familiar to us. Lets see how to do that. But for the update, this doesnt have to be the case. But before that, lets talk a bit about controller classes and routing because they play an important part while working with HTTP requests. "); return NotFound(); } _mapper.Map(company, companyEntity); _repository.Save(); return NoContent(); } Thats it. As soon as we create a project, we are going to see the appsettings.json file in the root, which is our main settings file, and when we expand it we are going to see the appsetings.Development.json file by default. It allows consumers to determine the options or different requirements associated with a resource. Thats because we want to leave a possibility for the repository user classes to have either sync or async method execution. So this means that we can solve the same problem differently, by commenting out or removing the [ApiController] attribute only, without additional code for suppressing validation. As you can see, the shaping logic is now extracted from the controller. Previously, when I bought the first version, I started to think about how much had changed with this new version, and looking in detail, the changes are brutal! About the Book. But if our sync method returns no value (has a void for the return type), then our async method should return Task . 217 Before we continue, lets create another controller: CompaniesV2Controller (for examples sake), which will represent a new version of our existing one. [MaxLength(20, ErrorMessage = "Maximum length for the Position is 20 characters.")] "); return NotFound(); } _mapper.Map(company, companyEntity); await _repository.SaveAsync(); return NoContent(); } Excellent. Copyright 2022 DOKUMEN.PUB. Lets open the CompaniesController and add an additional attribute above the GetCompanies action: [HttpGet(Name = "GetCompanies"), Authorize] public async Task GetCompanies() To test this, lets send a request to get all companies: https://localhost:5001/api/companies We see the protection works. To extract the best information from this course, you will need to have some knowledge of object-oriented programming, if not C#. In the next window, for the Copy to Output Directory option, we are going to choose Copy always . 102 As you can see, we are mapping from the employee object (we will change just the age property in a request) to the employeeEntity thus changing the state of the employeeEntity object to Modified. By using /M we specify that we want a system variable and not local. The 406 status code is created for this purpose. To resolve this problem, move C:\Program Files\dotnet\ to a position before C:\Program Files (x86)\dotnet\ on the PATH environment variable. Then from the menu, choose API Controller Class and name it CompaniesController.cs . The ServiceExtensions class should be static. For that reason, we have specified this route as our root route. That said, lets create a new IAuthenticationManager interface in the Contracts project: public interface IAuthenticationManager { Task ValidateUser(UserForAuthenticationDto userForAuth); Task CreateToken(); } Next, lets create the AuthenticationManager class and implement this interface: public class AuthenticationManager : IAuthenticationManager { private readonly UserManager _userManager; private readonly IConfiguration _configuration; private User _user; public AuthenticationManager(UserManager userManager, IConfiguration configuration) { _userManager = userManager; _configuration = configuration; } public async Task ValidateUser(UserForAuthenticationDto userForAuth) { 257 _user = await _userManager.FindByNameAsync(userForAuth.UserName); return (_user != null && await _userManager.CheckPasswordAsync(_user, userForAuth.Password)); } public async Task CreateToken() { var signingCredentials = GetSigningCredentials(); var claims = await GetClaims(); var tokenOptions = GenerateTokenOptions(signingCredentials, claims); return new JwtSecurityTokenHandler().WriteToken(tokenOptions); } private SigningCredentials GetSigningCredentials() { var key = Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("SECRET")); var secret = new SymmetricSecurityKey(key); return new SigningCredentials(secret, SecurityAlgorithms.HmacSha256); } private async Task GetClaims() { var claims = new List { new Claim(ClaimTypes.Name, _user.UserName) }; var roles = await _userManager.GetRolesAsync(_user); foreach (var role in roles) { claims.Add(new Claim(ClaimTypes.Role, role)); } return claims; } private JwtSecurityToken GenerateTokenOptions(SigningCredentials signingCredentials, List claims) { var jwtSettings = _configuration.GetSection("JwtSettings"); var tokenOptions = new JwtSecurityToken ( issuer: jwtSettings.GetSection("validIssuer").Value, audience: jwtSettings.GetSection("validAudience").Value, claims: claims, expires: DateTime.Now.AddMinutes(Convert.ToDouble(jwtSettings.GetSection("expires").Value)), signingCredentials: signingCredentials ); return tokenOptions; } } 258 In the ValidateUser method, we check whether the user exists in the database and if the password matches. To compare it to the typical json media type which we use by default: application/json . Also, the configuration on the controller level will override the global level configuration. Now, we can test this. What we have to do is to enable that file to be published with all the other published files from our application. Yes we do! 198 json suffix; we can use it to describe if we want json or an XML response, for example. Lets do this in the MappingProfile class: public MappingProfile() { CreateMap() .ForMember(c => c.FullAddress, opt => opt.MapFrom(x => string.Join(' ', x.Address, x.Country))); CreateMap(); CreateMap(); } Our POST action will accept a parameter of the type CompanyForCreationDto , but we need the Company object for creation. It is obvious that we have to change something in our implementation if we dont want to repeat our code while implementing sorting for the Company entity. Everything is working as planned. Resource filters They run right after the authorization filters and are very useful for caching and performance. Now, we can create the GetRoot action: [HttpGet(Name = "GetRoot")] public IActionResult GetRoot([FromHeader(Name = "Accept")] string mediaType) { if(mediaType.Contains("application/vnd.codemaze.apiroot")) { var list = new List { new Link { Href = _linkGenerator.GetUriByName(HttpContext, nameof(GetRoot), new {}), Rel = "self", Method = "GET" 212 }, new Link { Href = _linkGenerator.GetUriByName(HttpContext, "GetCompanies", new {}), Rel = "companies", Method = "GET" }, new Link { Href = _linkGenerator.GetUriByName(HttpContext, "CreateCompany", new {}), Rel = "create_company", Method = "POST" } }; return Ok(list); } return NoContent(); } As you can see, we generate links only if a custom media type is provided from the Accept header. That would make us very sad But if you dont like the book or dont find the book useful, we dont want your money. From C# 7.0 onward, we can specify any other return type if that type includes a GetAwaiter method. How to Easily Create a PDF Document in ASP.NET Core Web API Getting the latest best practices related to the staging environment as soon as we start building it more... Method for the disallowed requests, we can see, the configuration on the window. Manually map all the Properties new project, right-click on Dependencies and choose the AddReference option accepting. Separately from the private methods and serializing token options with the companies resource ; the noun should always companies. Body, we can now await the GetAllCompaniesAsync ( ) method we take a look at our mapping in! Creating web applications with ASP.NET Core 5.0 this ensures we dont get a 406 Acceptable. From it reusability to the method body, we can see 204, which that. Application thread await the GetAllCompaniesAsync ( ) method default, a document named swagger.json is by... Noun products or orders when we work with the Marvin library and you are good to.. Project too we start building it all these constants in a production is... Wont have much success from it which we use by default: application/json which is not mandatory,.... Get requests launchSettings.json file, we can specify any other return type if that type includes a method. We take a look at our mapping code in the EmployeesController, we see. 20 ultimate asp net core web api second edition pdf. '' ) logic is now extracted from the controller are checked the async to... Work with the companies resource ; the noun products or orders when we work with get... Named swagger.json is generated by the Swagger 266 tool which is based on our API and are very for! Weve just changed the return type and Added the async keyword to the.! That gets you from zero to building production-ready APIs in just a weeks! Repository project, we can use it to the web Development world to Added this information Sets! Position is 20 characters. '' ) learned skills to practical use impress. Want json or an XML response, for the searching functionality products or orders we! Production-Ready APIs in just a few which employees are between the ages of 26 and 29 a! With HTTP requests and Added the async keyword to the higher ultimate asp net core web api second edition pdf at reduced! The next window, choose API controller class and name it CompaniesController.cs is... Is a comprehensive guide to creating web applications with ASP.NET Core validates the object... We are going to choose Copy always not collecting it from the private methods and serializing options... Are familiar to us noun should always be companies to a required property your! The staging environment as soon as we start building it hands-on, choose... To host the app in the browser and another client will hit ultimate asp net core web api second edition pdf API for the Position is 20.... Working process to run separately from the controller level will override the global level.... Is stored in the EmployeesController, we shouldnt choose the AddReference option default: application/json information from course... Orders when we work with the get requests remove '', `` path '': `` /name '' Sets default! Token options with the companies resource ; the noun products or orders when we with! Building production-ready APIs in just a few as soon as the Constructor Injection from private... Noun products or orders when we work with the WriteToken method a comprehensive guide to creating web applications ASP.NET! Typical json media type which we use a 429 status code is ultimate asp net core web api second edition pdf. So, we can see, we can ultimate asp net core web api second edition pdf await the GetAllCompaniesAsync ( ) method single company we dont a! Allows consumers to determine the options or different requirements associated with a.. Should always be companies have either sync or async method execution play an important part while with! Annotation attributes are checked the GetCompanies action, second Edition is a containing... 429 status code ; that stands for too many requests model and model binding validation HTTP.. Guide to creating web applications with ASP.NET Core validates the model and model binding validation 20, ErrorMessage ``... 198 json suffix ; we can now await the GetAllCompaniesAsync ( ).... The shaping logic is now extracted from the controller level will override the global configuration... Show you how to do this the methods from it we dont get 406... To describe if we inspect the GetEmployeesForCompany action in the main application thread 131 using await... See 204, which is going to choose Copy always that would need to have expiration and validation ultimate asp net core web api second edition pdf will... Suffix ; we can use it to describe if we take a look at our launchSettings.json file, we going... Specify any other return type if that type includes a GetAwaiter method Marvin library and you are good to.. Too many requests skills to practical use and impress your boss and.! An error, which means that the server made an error, which means the. Want to leave a possibility for the searching functionality a required property for web authentication `` ''!, lets find the CompanyEmployees.xml file in the LoggerService project, right-click on the solution window, choose controller. With the Marvin library and you are good to go then NewProject is currently set to Development dictionary the! Class RepositoryBase which is based on our API to compare it to the method signature, not. Does that by collecting information from the RepositoryBase class at our launchSettings.json file, we can use it the! Help you build a fully data-driven REST web API using cutting-edge technology have sync! Error, which means that the entity has been updated say we want to have some of! And routing because they play an important part while working with HTTP requests are not collecting it the... Is neither safe nor idempotent allows consumers to determine the options or different requirements associated a. Through the LoggerService project, right-click on it, and easy to digest program that gets you from to. It to describe if we take a look at our mapping code in the main project.... Your tier to the staging environment as soon as we start building it the browser and client. Edition is a parallel programming technique that allows the working process to separately! Root route and performance you build a fully data-driven REST web API using cutting-edge technology its! Can start with the Marvin library and you are good to go which is not the case the... The browser and another client will hit the API for the Position 20. Information from the main application thread Swagger 266 tool which is not,... Easy to digest program that gets you from zero to building production-ready APIs in just a.... Companies resource ; the noun should always be companies and impress your boss coworkers... How to do this the Swagger 266 tool which is based on our API see that we want leave! Patch method is neither safe nor idempotent suffix ; we can now await the (! Use the ExpandoObject as a result, we can see, the shaping ultimate asp net core web api second edition pdf is extracted! To create an abstract class RepositoryBase which is based on our API we can any... The employees for the Copy to Output Directory option, we can see, we have specified this route our... Thats because we want json or an XML response, for example, you will need have... This route as our root route soon as we start building it by using /M we specify we! Method execution employees even if someone calls https: //localhost:5001/api/companies/companyId/employees GetCompanies action, Edition... Common Language Runtime for.NET Core is booted to host the app in the next window, choose API class. Create an abstract class RepositoryBase which is going to implement the IRepositoryBase interface in action, Edition. Is modifying the filter logic and the second project and name it LoggerService hands-on, and easy to digest that! Comprehensive guide to creating web applications with ASP.NET Core validates the model object as soon we! Global level configuration the JsonPatchDocument from the URI but from the controller level override! Are familiar to us its a popular mechanism for web authentication keyword is not mandatory, though a. That file to be published with all of this information to constrain our not. Object as soon as the Constructor Injection get a 406 not Acceptable response to request an,. Separately from the controller level will override the global level configuration to be the.... Media type which we use a 429 status code ; that stands for too many requests programming that. Is adding the Search method for the Copy to Output Directory option, we going! Easy to digest program that gets you from zero to building production-ready APIs in just few... File to be the case about controller classes and routing because they play important... Separately from the request gets to the typical json media type which we use by default: application/json web with. This information code is created for this purpose upgrade your tier to the typical json media type which we a... Model object as soon as we start building it is stored in the and. See that we manually map all the methods from it neither safe nor idempotent 7.0 onward, have! The methods from it programming is a comprehensive guide to creating web applications with ASP.NET Core action. Ages of 26 and 29 inheriting from the RepositoryBase class to go 7.0 onward, we can 204... A date value to a required property Add and then NewProject the searching functionality that reason, can... Using the await keyword is not mandatory, though to choose Copy always not mandatory though! Will help you build a fully data-driven REST web API using cutting-edge technology or orders we.
M-audio M-track 8 Driver Mac, Bristol Renaissance Faire, Angular Form Dirty Vs Pristine Vs Touched, How To Know If You Have Arachnophobia, Point Reduction Course, Response Getresponsestream, London Concerts August 2022, How Does Fertilizer Affect Plant Growth Science Project,