These tools are emerging from my love towards simplicity, work automation and clean APIs.
Project aiming ASP.NET Core 1.0.
Dependencies:
What it is:
DotNetNinja.AspNetCore.ImageResizer
contains few features:
Size
structure:
- which contains properties
int? Width
andint? Height
(thanks to it you can give only one, desired dimension and auto-scale the other).
IImageResizer
with ImageResizer
service implementation:
- it takes image from input path, resizes it to target
Size
and saves to output path.
IImagePathGenerator
with ImagePathGenerator
service implementation:
- which produces output path for images of given
Size
.
ImageResizerMiddleware
:
- thanks to interrupting HTTP pipeline, it gives you ability to resize images on the fly and use
<img>
element like this:
<img src="some-image.jpg"> <!-- some-image.jpg in original size -->
<img src="some-image.jpg?w=200"> <!-- some-image.jpg resized to 200px width and proportional height -->
<img src="some-image.jpg?w=200&h=100"> <!-- some-image.jpg resized to 200px width and 100 px height -->
<img src="some-image.jpg?h=100"> <!-- some-image.jpg resized to 100 px height -->
ImageServerMiddleware
:
- it only serves already resized images (gives 404 HTTP response if no particular size was found).
Sample usage:
In order to use default implementations just add following to your Startup.cs
:
using DotNetNinja.AspNetCore.ImageResizer;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// adds ImageResizer and ImagePathGenerator singleton services implementations
services.AddImageResizer();
}
public void Configure(IApplicationBuilder app)
{
app.UseImageResizer(); // for ImageResizerMiddleware
// or:
app.UseImageServer(); // for ImageServerMiddleware
}
}
Project aiming ASP.NET Core 1.0.
Dependencies:
- ASP.NET Core 1.0 MVC
- Entity Framework Core
What it is:
Custom user management, authentication and authorization (the latter coming in the future) library for ASP.NET Core with Entity Framework Core projects.
DotNetNinja.AspNetCore.UserAccess
gives you:
User
class:
- model representing user of application.
ISaltGenerator
with RandomSaltGenerator
implementation:
- service used to obtain salt for password hashing.
IHashManager
with HashManager
implementation:
- service used to generate and verify password hashes (PBKDF2 by default).
IUserService
with UserService
implementation:
- service providing basic users operations like create, delete, log in, log out.
UserAccessFilter
:
- MVC authentication filter that lets you control access to your controllers and actions in convenient way.
UnauthorizedRedirectionMiddleware
:
- middleware that lets you redirect all HTTP 401 unauthorized responses (which are returned by default if authentication fails).
Sample usage:
Add DbSet<User>
to your app's DbContext
.
using DotNetNinja.AspNetCore.UserAccess;
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
// ...
}
Configure your Startup.cs
:
using DotNetNinja.AspNetCore.UserAccess;
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// ...
// you also have to register your DbContext and Mvc services
services.AddUserAccess<AppDbContext>();
// ...
}
public void Configure(IApplicationBuilder app)
{
// ...
// optional:
app.UseUnauthorizedRedirection("/users/login"); // unauthorized requests will be redirected to /users/login route
// ...
}
}
Now you can restrict access to your controllers and actions by adding [UserAccess]
attribute to those:
using DotNetNinja.AspNetCore.UserAccess;
public class HomeController : Controller
{
// this action can be accessed by anyone:
public IActionResult Index()
{
return View();
}
// this action can be accessed only if request contains cookie with valid access token:
[UserAccess]
public IActionResult RestrictedAction()
{
return View();
}
}
// every action in this controller can be accessed only if request contains cookie with valid access token:
[UserAccess]
public class RestrictedController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult DoSomething()
{
// ...
return View();
}
}
In order to access basic user management functionality you can use IUserService
.
Sample of log in/log out controller with the injected service:
using DotNetNinja.AspNetCore.UserAccess;
public class UsersController : Controller
{
IUserService _userService;
public UsersController(IUserService userService)
{
_userService = userService;
}
public IActionResult LogIn()
=> View();
[HttpPost]
public async Task<IActionResult> LogIn(string login, string password)
{
var token = await _userService.LogInAsync(login, password);
if (token == null)
{
return Unauthorized();
}
return RedirectToAction("Index", "Home");
}
[UserAccess]
public async Task<IActionResult> LogOut()
{
await _userService.LogOutAsync();
return RedirectToAction("Index", "Home");
}
}
Library giving access to abstract class PropertyChangedNotifier
which implements INotifyPropertyChanged
and provides convenient mechanisms for notifying properties change. The mechanisms are type-safe and allow using IntelliSense.
No more magic strings causing headache while debugging!
Sample usage:
Derive from PropertyChangedNotifier:
using DotNetNinja.NotifyPropertyChanged;
public class SampleObject : PropertyChangedNotifier
{
// ...
}
There are 3 ways you can notify property change:
- implicitly (my personal favorite)
public int Property
{
get { return _property; }
set { SetProperty(ref _property, value); }
}
int _property;
- with expression tree selector
public int Property
{
get { return _property; }
set { SetProperty(ref _property, value, () => Property); }
}
int _property;
- with
nameof
keyword
public int Property
{
get { return _property; }
set { SetProperty(ref _property, value, nameof(Property)); }
}
int _property;
It's simple, fluent API that provides little bits of C# 7's pattern-matching-like functionality. Functional programming features are cool!
Sample usage:
interface IFoo
{
void Foo();
}
interface IGoo
{
bool IsValid { get; }
void Goo();
}
interface IHoo
{
void Hoo();
}
void SampleGeneric<T>(T item)
{
item
.When<IFoo>(i => i.Foo()) // lambda calling i.Foo() fires if item implements IFoo
.When<IGoo>((i, filtering) => // lambda fires if item implements IGoo
{
if (i.IsValid)
{
i.Goo();
filtering.Break(); // if control flow reaches this point, no further type tests will be performed
}
})
.When<IHoo>(i => i.Hoo()) // this is reached only if filtering.Break() wasn't called
.ThrowIfNotRecognized(); // if no type was recognized, InvalidOperationException is thrown
}
// note: API doesn't automatically break after successful type test unless broken explicitly by user (just like in IGoo case or with BreakIfRecognized() method).
Simple WPF yes/no dialog designed for both vanilla and model-view-viewModel
with dependency injection
scenarios.
Sample usage:
Via static method:
using DotNetNinja.Wpf.ConfirmDialog;
if (await ConfirmDialog.ConfirmAsync("Do you really wanna do this?"))
{
// confirmed
}
else
{
// declined
}
In MVVM with DI (assuming your IoC container resolves IConfirmator
to ConfirmDialogConfirmator
):
using DotNetNinja.Wpf.ConfirmDialog;
public class ViewModel
{
// commands, services and stuff
IConfirmator _confirmator;
public ViewModel(IConfirmator confirmator)
{
_confirmator = confirmator;
}
public async Task DoSomethingAsync()
{
if (await _confirmator.ConfirmAsync("Are you sure?"))
{
// confirmed
}
else
{
// declined
}
}
}
Lib provides also AlwaysYesConfirmator
and AlwaysNoConfirmator
types for mocking purposes.