dotnet --list-sdks
- wyświetlenie listy zainstalowanych SDKdotnet new globaljson
- utworzenie pliku global.jsondotnet new globaljson --sdk-version {version}
- utworzenie pliku global.json i ustawienie wersji SDKdotnet new --list
- wyświetlenie listy dostępnych szablonówdotnet new {template}
- utworzenie nowego projektu na podstawie wybranego szablonudotnet new {template} -o {output}
- utworzenie nowego projektu w podanym katalogudotnet restore
- pobranie bibliotek nuget na podstawie pliku projektudotnet build
- kompilacja projektudotnet run
- uruchomienie projektudotnet run {app.dll}
- uruchomienie aplikacjidotnet test
- uruchomienie testów jednostkowychdotnet run watch
- uruchomienie projektu w trybie śledzenia zmiandotnet test
- uruchomienie testów jednostkowych w trybie śledzenia zmiandotnet add {project.csproj} reference {library.csproj}
- dodanie odwołania do bibliotekidotnet remove {project.csproj} reference {library.csproj}
- usunięcie odwołania do bibliotekidotnet new sln
- utworzenie nowego rozwiązaniadotnet sln {solution.sln} add {project.csproj}
- dodanie projektu do rozwiązaniadotnet sln {solution.sln} remove {project.csproj}
- usunięcie projektu z rozwiązaniadotnet publish -c Release -r {platform}
- publikacja aplikacjidotnet publish -c Release -r win10-x64
- publikacja aplikacji dla Windowsdotnet publish -c Release -r linux-x64
- publikacja aplikacji dla Linuxdotnet publish -c Release -r osx-x64
- publikacja aplikacji dla MacOSdotnet add package {package-name}
- dodanie pakietu nuget do projektudotnet remove package {package-name}
- usunięcie pakietu nuget do projektu+ Solution
|
+ - Console
|
+ - Models
|
+ - Infrastructure
|
+ - Api
Instalacja
dotnet add package ServiceStack.HttpClient
Pobranie listy obiektów
public async Task<IEnumerable<Customer>> Get()
{
var url = $"{baseUri}/api/customers";
var json = await url.GetJsonFromUrlAsync();
var customers = json.FromJson<ICollection<Customer>();
return customers;
}
Przekazanie parametrów
public async Task<IEnumerable
url = AddQueryCustomerParams(customerSearchCriteria, url);
var json = await url.GetJsonFromUrlAsync();
var customers = json.FromJson<ICollection
return customers; }
private static string AddQueryCustomerParams(CustomerSearchCriteria searchCriteria, string url) { if (!string.IsNullOrEmpty(searchCriteria.CustomerNumber)) url = url.AddQueryParam(nameof(CustomerSearchCriteria.CustomerNumber), searchCriteria.CustomerNumber);
if (!string.IsNullOrEmpty(searchCriteria.City))
url = url.AddQueryParam(nameof(CustomerSearchCriteria.City), searchCriteria.City);
if (!string.IsNullOrEmpty(searchCriteria.Street))
url = url.AddQueryParam(nameof(CustomerSearchCriteria.Street), searchCriteria.Street);
if (!string.IsNullOrEmpty(searchCriteria.Country))
url = url.AddQueryParam(nameof(CustomerSearchCriteria.Country), searchCriteria.Country);
return url;
}
## .NET Standard
## Protokół HTTP
żądanie (request)
GET /docs/index.html HTTP/1.1 host: www.altkom.pl {blank line}
odpowiedź (response)
HTTP/1.1 200 OK Content-Length: 308 Content-Type: text/html
Hello World!
----
żądanie (request)
GET /api/customers HTTP/1.1 host: www.altkom.pl Accept: application/json {blank line}
odpowiedź (response)
HTTP/1.1 200 OK Content-Length: 308 Content-Type: application/xml
## SOAP
żądanie (request)
POST /myservice.asmx HTTP/1.1 host: www.altkom.pl Content-Type: application/xml
## REST API
| Akcja | Opis |
|--------|-----------------------|
| GET | Pobierz |
| POST | Utwórz |
| PUT | Podmień |
| DELETE | Usuń |
| PATCH | Zmień częściowo |
| HEAD | Czy zasób istnieje |
prawidłowe
GET api/customers GET api/customers/10 GET api/customers/altkom GET api/customers?city=Katowice&Street=Opolska DELETE api/customers/10
nieprawidłowe
GET api/customers?Id=10 GET api/customers/delete?Id=10 GET api/customers/GetCustomerByCity?city=Poznan
## Porównanie ASP.NET MVC i .NET Core
ASP.NET MVC
Controller ApiController View(model) Ok(model)
.NET Core
Controller -> BaseController View(model) Ok(model)
## Wstrzykiwanie zależności
DI/IoC
~~~ csharp
interface Factory
{
T Create<T>();
}
| Key | Value | Cykl zycia
| ICustomerRepository | FakeCustomerRepository | Singleton
| CustomerFaker | CustomerFaker |
| AddressFaker | AddressFaker |
ADO.NET | Dapper/PetaPOCO | EF Core/nHibernate
Utworzenie klasy opcji
public class CustomerOptions
{
public int Quantity { get; set; }
}
Plik konfiguracyjny appsettings.json
{
"CustomersModule": {
"Quantity": 40
},
dotnet add package Microsoft.Extensions.Options
public class FakeCustomersService
{
private readonly CustomerOptions options;
public FakeCustomersService(IOptions<CustomerOptions> options)
{
this.options = options.Value;
}
}
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false)
.AddXmlFile("appsettings.xml", optional: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CustomerOptions>(Configuration.GetSection("CustomersModule"));
}
}
public void ConfigureServices(IServiceCollection services)
{
var customerOptions = new CustomerOptions();
Configuration.GetSection("CustomersModule").Bind(customerOptions);
services.AddSingleton(customerOptions);
services.Configure<CustomerOptions>(Configuration.GetSection("CustomersModule"));
}
Plik Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(options =>
{
options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; // Wyłączenie generowania wartości null w jsonie
options.SerializerSettings.Converters.Add(new StringEnumConverter(camelCaseText: true)); // Serializacja enum jako tekst
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; // Zapobieganie cyklicznej serializacji
})
}
Plik Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc(options => options.RespectBrowserAcceptHeader = true)
.AddXmlSerializerFormatters();
}
t1 -----+=============+------------------->
t1 -----+-------+------------------------>
| | |
t2 -----+=============|------------------>
| |
t3 -------------+=============|---------->
|
t4 ----------------------+=======|------->
middleware (filter)
request -> ----|---|-----|-----|-----|===Get(100)====|---response-------->
Headers | Key | Value |
---|---|---|
Authorization | Basic {Base64(login:password)} |
Utworzenie interfejsu
public interface ICustomerRepository : IEntityRepository<Customer>
{
bool TryAuthorize(string username, string hashPasword, out Customer customer);
}
Implementacja repozytorium
public class DbCustomerRepository : ICustomerRepository
{
private readonly MyContext context;
public DbCustomerRepository(MyContext context)
{
this.context = context;
}
public bool TryAuthorize(string username, string hashPasword, out Customer customer)
{
customer = context.Customers.SingleOrDefault(e => e.UserName == username && e.HashPassword == hashPasword);
return customer != null;
}
}
public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
private readonly ICustomerRepository customerRepository;
public BasicAuthenticationHandler(
ICustomerRepository customerRepository,
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
this.customerRepository = customerRepository;
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.ContainsKey("Authorization"))
return AuthenticateResult.Fail(string.Empty);
var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
if (authHeader.Scheme != "Basic")
return AuthenticateResult.Fail(string.Empty);
var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
string[] credentials = Encoding.UTF8.GetString(credentialBytes).Split(':');
if (!customerRepository.TryAuthorize(credentials[0], credentials[1], out Customer customer))
{
return AuthenticateResult.Fail("Invalid username or password");
}
ClaimsIdentity identity = new ClaimsIdentity("Basic");
identity.AddClaim(new Claim(ClaimTypes.HomePhone, "555-444-333"));
identity.AddClaim(new Claim(ClaimTypes.Role, "Developer"));
ClaimsPrincipal principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, "Basic");
return AuthenticateResult.Success(ticket);
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("BasicAuthorization")
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthorization", null);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMvc();
}
Headers | Key | Value |
---|---|---|
Authorization | Bearer {token} |
W formacie Swagger/OpenApi
dotnet add package Swashbuckle.AspNetCore
Plik Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services
.AddSwaggerGen(c => c.SwaggerDoc("v1", new Info { Title = "My Api", Version = "1.0" }));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"));
}