Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions aspnetcore/includes/duende-identity-server-10.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. To secure web APIs and SPAs, use one of the following:

* [Microsoft Entra ID](/azure/api-management/api-management-howto-protect-backend-with-aad)
* [Duende Identity Server](https://docs.duendesoftware.com)

Duende Identity Server is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. Duende Identity Server enables the following security features:

* Authentication as a Service (AaaS)
* Single sign-on/off (SSO) over multiple application types
* Access control for APIs
* Federation Gateway

> [!IMPORTANT]
> [Duende Software](https://duendesoftware.com/) might require you to pay a license fee for production use of Duende Identity Server.
Comment thread
timdeschryver marked this conversation as resolved.

For more information, see the [Duende Identity Server documentation (Duende Software website)](https://docs.duendesoftware.com).
114 changes: 58 additions & 56 deletions aspnetcore/tutorials/first-mongo-app.md

Large diffs are not rendered by default.

518 changes: 518 additions & 0 deletions aspnetcore/tutorials/first-mongo-app/includes/first-mongo-app-9.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.7" />
<PackageReference Include="MongoDB.Driver" Version="3.8.0" />
<PackageReference Include="NSwag.AspNetCore" Version="14.7.1" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@BookStoreApi_HostAddress = https://localhost:56874

GET {{BookStoreApi_HostAddress}}/books

###

@id=string
GET {{BookStoreApi_HostAddress}}/books/{{id}}

###

POST {{BookStoreApi_HostAddress}}/books
Content-Type: application/json

{
//Book
}

###

DELETE {{BookStoreApi_HostAddress}}/books/{{id}}

###
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// <snippet_UsingSystemTextJsonSerialization>
using System.Text.Json.Serialization;
// </snippet_UsingSystemTextJsonSerialization>
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace BookStoreApi.Models;

public class Book
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; }

// <snippet_BookName>
[BsonElement("Name")]
[JsonPropertyName("Name")]
public string BookName { get; set; } = null!;
// </snippet_BookName>

public decimal Price { get; set; }

public string Category { get; set; } = null!;

public string Author { get; set; } = null!;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace BookStoreApi.Models;

public class BookStoreDatabaseSettings
{
public string ConnectionString { get; set; } = null!;

public string DatabaseName { get; set; } = null!;

public string BooksCollectionName { get; set; } = null!;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// <snippet_UsingModels>
using BookStoreApi.Models;
// </snippet_UsingModels>
// <snippet_UsingServices>
using BookStoreApi.Services;
// </snippet_UsingServices>

// <snippet_JsonOptions>
// <snippet_BooksService>
// <snippet_BookStoreDatabaseSettings>
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.Configure<BookStoreDatabaseSettings>(
builder.Configuration.GetSection("BookStoreDatabase"));
// </snippet_BookStoreDatabaseSettings>

builder.Services.AddSingleton<BooksService>();
// </snippet_BooksService>

builder.Services.Configure<Microsoft.AspNetCore.Http.Json.JsonOptions>(options =>
{
options.SerializerOptions.PropertyNamingPolicy = null;
});
// </snippet_JsonOptions>

// Add services to the container.
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

// <snippet_UseSwagger>
var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.UseSwaggerUi(options =>
{
options.DocumentPath = "/openapi/v1.json";
});
}
// </snippet_UseSwagger>

// <snippet_MapEndpoints>
var booksGroup = app.MapGroup("/books");

booksGroup.MapGet("/", async (BooksService booksService) =>
{
var books = await booksService.GetAsync();
return Results.Ok(books);
});

booksGroup.MapGet("/{id:length(24)}", async (string id, BooksService booksService) =>
{
var book = await booksService.GetAsync(id);

return book is null ? Results.NotFound() : Results.Ok(book);
});

booksGroup.MapPost("/", async (Book newBook, BooksService booksService) =>
{
await booksService.CreateAsync(newBook);

return Results.Created($"/books/{newBook.Id}", newBook);
});

booksGroup.MapPut("/{id:length(24)}", async (string id, Book updatedBook, BooksService booksService) =>
{
var book = await booksService.GetAsync(id);

if (book is null)
{
return Results.NotFound();
}

updatedBook.Id = book.Id;

await booksService.UpdateAsync(id, updatedBook);

return Results.NoContent();
});

booksGroup.MapDelete("/{id:length(24)}", async (string id, BooksService booksService) =>
{
var book = await booksService.GetAsync(id);

if (book is null)
{
return Results.NotFound();
}

await booksService.RemoveAsync(id);

return Results.NoContent();
});
// </snippet_MapEndpoints>

app.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// <snippet_File>
using BookStoreApi.Models;
using Microsoft.Extensions.Options;
using MongoDB.Driver;

namespace BookStoreApi.Services;

// <snippet_ctor>
public class BooksService(IOptions<BookStoreDatabaseSettings> bookStoreDatabaseSettings)
{
private readonly IMongoCollection<Book> _booksCollection = new MongoClient(bookStoreDatabaseSettings.Value.ConnectionString)
.GetDatabase(bookStoreDatabaseSettings.Value.DatabaseName)
.GetCollection<Book>(bookStoreDatabaseSettings.Value.BooksCollectionName);
// </snippet_ctor>
Comment thread
timdeschryver marked this conversation as resolved.

public async Task<List<Book>> GetAsync() =>
await _booksCollection.Find(_ => true).ToListAsync();

public async Task<Book?> GetAsync(string id) =>
await _booksCollection.Find(x => x.Id == id).FirstOrDefaultAsync();

public async Task CreateAsync(Book newBook) =>
await _booksCollection.InsertOneAsync(newBook);

public async Task UpdateAsync(string id, Book updatedBook) =>
await _booksCollection.ReplaceOneAsync(x => x.Id == id, updatedBook);

public async Task RemoveAsync(string id) =>
await _booksCollection.DeleteOneAsync(x => x.Id == id);
}
// </snippet_File>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"BookStoreDatabase": {
"ConnectionString": "mongodb://localhost:27017",
"DatabaseName": "BookStore",
"BooksCollectionName": "Books"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
20 changes: 20 additions & 0 deletions aspnetcore/tutorials/first-mongo-app/samples_snapshot/10.x/Book.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace BookStoreApi.Models;

public class Book
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; }

[BsonElement("Name")]
public string BookName { get; set; } = null!;

public decimal Price { get; set; }

public string Category { get; set; } = null!;

public string Author { get; set; } = null!;
}
Loading