dangl - Dangl.Data.Shared 1.6.0-beta0006

Dangl.Data.Shared - www.dangl-it.com

PM> Install-Package Dangl.Data.Shared -Version 1.6.0-beta0006 -Source https://www.myget.org/F/dangl/api/v3/index.json

Copy to clipboard

> nuget.exe install Dangl.Data.Shared -Version 1.6.0-beta0006 -Source https://www.myget.org/F/dangl/api/v3/index.json

Copy to clipboard

> dotnet add package Dangl.Data.Shared --version 1.6.0-beta0006 --source https://www.myget.org/F/dangl/api/v3/index.json

Copy to clipboard
<PackageReference Include="Dangl.Data.Shared" Version="1.6.0-beta0006" />
Copy to clipboard
source https://www.myget.org/F/dangl/api/v3/index.json

nuget Dangl.Data.Shared  ~> 1.6.0-beta0006
Copy to clipboard

> choco install Dangl.Data.Shared --version 1.6.0-beta0006 --source https://www.myget.org/F/dangl/api/v2

Copy to clipboard
Import-Module PowerShellGet
Register-PSRepository -Name "dangl" -SourceLocation "https://www.myget.org/F/dangl/api/v2"
Install-Module -Name "Dangl.Data.Shared" -RequiredVersion "1.6.0-beta0006" -Repository "dangl" -AllowPreRelease
Copy to clipboard

Dangl.Data.Shared

Build Status
NuGet

This solution builds both Dangl.Data.Shared and Dangl.Data.Shared.AspNetCore packages.

The aim of this solution is to consolidate simple, reused code such as ApiError or RepositoryResult<T>.

Link to docs:

Changelog

ModelStateValidationFilter

The ModelStateValidationFilter is a simple wrapper that returns a BadRequestObjectResult with an ApiError body when the passed ModelState of an action is invalid. This allows to keep controlls free of basic model state validation logic.

To use the filter, it must be configured in the AddMvc() call in ConfigureServices:

services.AddMvc(options =>
    {
        options.Filters.Add(typeof(ModelStateValidationFilter));
    });

RequiredFormFileValidationFilter

The RequiredFormFileValidationFilter is a simple wrapper that returns a BadRequestObjectResult with an ApiError body when the invoked Controller action has parameters of type IFormFile that are annotated with [Required] but have no value bound.

For example, the following action makes use of the filter:

[HttpPost("RequiredFormFile")]
public IActionResult RequiredFormFile([Required]IFormFile formFile)
{
    return Ok();
}

To use the filter, it must be configured in the AddMvc() call in ConfigureServices:

services.AddMvc(options =>
    {
        options.Filters.Add(typeof(RequiredFormFileValidationFilter));
    });

BiggerThanZeroAttribute

The BiggerThanZeroAttribute is a ValidationAttribute that can be applied to int or long properties to ensure their values are greater than zero.

JsonOptionsExtensions

The JsonOptionsExtensions class configures default Json options for the Newtonsoft Json serializer. It ignores null values, uses the EmptyEnumDeserializer (derived from StringEnumConverter and maps empty or null enum values to their default value), the GuidStringDeserializer to deserialize empty or null Guid values to an empty guid and ignores default values for Guid, DateTime and DateTimeOffset.

StringFilterQueryExtensions

The StringFilterQueryExtensions class has a .Filter() extension method with the following signature:

public static IQueryable<T> Filter<T>(this IQueryable<T> queryable,
    string filter,
    Func<string, Expression<Func<T, bool>>> filterExpression,
    bool transformFilterToLowercase)

It can be used to apply a string filter. Meaning, you supply a string filter parameter and a filterExpression, and the filter is split into word segments and each applied to the filterExpression.

Example

Let's you you want to implement a dynamic filter, e.g. if the user enters two words, you want to check if both of the words are contained in the value.
So, the user input maybe looks like this: hello world, and your filter looks like x => y => y.Contains(x). Instead of you having to manually split the string, you can now do something like this:

queryable.Filter("hello world", x => y => y.Contains(x), transformFilterToLowercase: false);

This would then get translated to something like this:

// The splitted query is "hello" and "world"
queryable.Where(q => q.Contains("hello") && q.Contains("world"));

You can also optionally tell it to transform all single segements of your filter to lowercase.

In EntityFramework, you could use something like this to build a dynamic LIKE query:

var filter = "search query";
var filteredQuery = _context.Projects
    .Filter(filter, text => p =>
        EF.Functions.Like(p.Name, $"%{text}%")
        || EF.Functions.Like(p.ContactName, $"%{text}%")
        || EF.Functions.Like(p.Description, $"%{text}%"),
        transformFilterToLowercase: true);

IClaimBasedAuthorizationRequirement

The namespace Dangl.Data.Shared.AspNetCore.Authorization contains utilities that help in building authorization policies that check for existing claims on authenticated users. By default, claim values that are either true or represent a valid-until time in the future (like 2018-08-08T09:02:15.5732531Z) are considered valid and will lead to the requirement handler succeeding.

To use it, there is an interface for the requirements:

public interface IClaimBasedAuthorizationRequirement : IAuthorizationRequirement
{
    IReadOnlyList<string> ClaimNames { get; }
}

Now, a class can be defined that implements this interface and be added as requirement in a policy:

o.AddPolicy(AvaCloudConstants.CONVERSION_POLICY_NAME, policy => policy
                        .AddRequirements(new ConversionRequirement(requiredUserClaim, requiredClientClaim)));

And the IAuthorizationHandler must be configured in the services:

services.AddTransient<IAuthorizationHandler, ClaimBasedAuthorizationRequirementHandler<ConversionRequirement>>();

Finally, to use this policy in your controllers or actions, you need to add an Authorize attribute with the policy name:

[Authorize(Policy = AvaCloudConstants.CONVERSION_POLICY_NAME)]
[Route("api/[Controller]")]
public class CategoriesController : Controller

HttpHeadRequestMiddleware

This middleware transforms incoming Http HEAD requests internally to GET requests so that they can hit their intended target action. The body will be set to Stream.Null, so that only the response headers are being sent back to the client.
This should be called before the AddMvc() call, like this:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseHttpHeadToGetTransform();
    app.UseMvc();
}

If you're using ASP.NET Core 3.0 or later, you should use the middleware before the call to the routing middleware:

app.UseHttpHeadToGetTransform();
app.UseRouting();
app.UseEndpoints(endpoints => {
    endpoints.MapControllers();
});

CompressedRequestMiddleware

This middleware supports clients that send their requests either gzip or deflate compressed. This can be used when endpoints expect big upload sizes to save on transfer time.
This should be called before other calls, like this:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseClientCompressionSupport();
    app.UseMvc();
}

IUserLocaleService

This service has a single method: string GetUserLocale(); and should return the locale for the current Http request. The default implementation UserLocaleService will do the following:

  1. It must be initiated with a list of available, valid languages and a name for a cookie under which users can store their preffered locale
  2. For every request which has a locale set via the cookie, this locale is returned
  3. If no cookie is present or the locale in the cookie is not available, the Accept-Language Http header is parsed
  4. Otherwise, the first configured available locale is returned

The UserLocaleService is added automatically when you use the LocalizedSpaStaticFileExtensions.

LocalizedSpaStaticFileExtensions

The LocalizedSpaStaticFileExtensions can be used to serve localized Single Page Applications (SPAs). For example, a localized Angular application might generate these files in your wwwroot directory:

/dist/en/index.html
/dist/de/index.html

To be able to serve these index files depending on the request of the user, the extensions detect the user language via the IUserLocaleService and serve the correct files.

Additionally, it also tries to resolve relative paths for requests. For example, if the client requests /assets/picture.jpg, the extensions will try to serve the file from /dist/en/assets/picture.jpg if the user language is en. This makes it possible to serve assets that are placed relative to the SPA root folder, without requiring the client to know about the relative path or any other configuration on the SPA side.

Example

First, configure the service:

services.AddLocalizedSpaStaticFiles(languageCookieName: ".MyApp.Locale",
    availableLocales: new[] { "de", "en" },
    spaRootPath: "dist");

Then add this as the last action for the request pipeline:

// This serves localized SPA files from disk,
// e.g. from wwwroot/dist/en
app.UseLocalizedSpaStaticFiles("index.html");

Please note: IHttpContextAccessor must be available via dependency injection

EmptyFormFileValidator

The EmptyFormFileValidator class is used to generate an invalid ModelState in an ASP.NET Core Request pipeline if a parameter is of type IFormFile (or derived) but has a Length of zero bytes.

Example

Simply configure it in your MVC setup:

using Dangl.Data.Shared.AspNetCore.Validation;

namespace Dangl.Data.Shared.AspNetCore.Tests.Integration
{
    public class Startup
    {
        public virtual void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(mvcSetup =>
            {
                mvcSetup.AddEmptyFormFileValidator();
            });
        }
    }
}

CdnNoCacheAttribute

The CdnNoCacheAttribute is a class that can be applied to ASP.NET Core controller actions to append the following headers:

Cache-Control: no-store, no-cache, no-transform

This attribute should be used for API responses on Cloudflare CDN. It sets the 'Cache-Control' header to 'no-store, no-cache, no-transform'. Cloudflare will not automatically compress responses for unknown content types, and will also not automatically pass through compression. For example, returning mime type 'application/octet-stream' without an appropriate 'no-cache, no-transform' entry in 'Cache-Control' will make Cloudflare always return the response uncompressed, even if the original server did compress it.

Example:

[HttpGet("NoCacheNoTransform")]
[CdnNoCache]
public IActionResult NoCacheNoTransform()
{
    return Ok(new
    {
        Value = "Some Data"
    });
}

RouteNameExtensions

The RouteNameExtensions class offers string extensions that make working with controller and action names easier, e.g. you can do nameof(StatusController).WithoutControllerSuffex() to get the controller name Status without the Controller suffix. Similar features also exist for Async suffixes. The check is case insensitive, and will just return the original input if the suffix is not present.

Assembly Strong Naming & Usage in Signed Applications

This module produces strong named assemblies when compiled. When consumers of this package require strongly named assemblies, for example when they themselves are signed, the outputs should work as-is. The key file to create the strong name is adjacent to the csproj file in the root of the source project. Please note that this does not increase security or provide tamper-proof binaries, as the key is available in the source code per Microsoft guidelines

v1.6.0:

  • Added the EmptyEnumDeserializer and the GuidStringDeserializer. Both these classes are used to deserialize either Guids or Enums from null values or empty strings and will return the default values for them, e.g. Guid.Empty. They are automatically activated when using ConfigureDefaultJsonSerializerSettings

v1.5.0:

  • Drop netcoreapp3.0 target and add netcoreapp3.1 target

v1.4.0:

  • Add netstandard2.1 and netcoreapp3.0 targets

v1.3.1:

  • Add CamelCaseDefaultValuesContractResolver

v1.3.0:

  • The generated assemblies now have a strong name. This is a breaking change of the binary API and will require recompilation on all systems that consume this package. The strong name of the generated assembly allows compatibility with other, signed tools. Please note that this does not increase security or provide tamper-proof binaries, as the key is available in the source code per Microsoft guidelines

v1.2.0:

  • Move JsonExtensions from Dangl.Data.Shared.AspNetCore to Dangl.Data.Shared

v1.1.1:

  • Add EmptyFormFileValidator with extensions to support the generation of an invalid ModelState if a parameter of type IFormFile (or derived) is passed with a Length of zero bytes

v1.1.0:

  • The Dangl.Data.Shared.AspNetCore package was updated to ASP.NET Core 2.2
  • Add LocalizedSpaStaticFileExtensions to help serving localized Single Page Applications (SPAs)
  • Add IUserLanguageService with default implementation

v1.0.10:

  • Add CompressedRequestMiddleware to support clients sending compressed request bodies

v1.0.9:

  • Add HttpHeadRequestMiddleware to support Http HEAD requests to all actions supporting originally only Http GET

v1.0.8:

  • Add IClaimBasedAuthorizationRequirement and supporting functionality

v1.0.7:

  • Add JsonOptionsExtensions

v1.0.6:

  • Rename FileResult to FileResultContainer

v1.0.5:

  • Add FileResult

v1.0.3:

  • Add logging to ModelStateValidationFilter if invalid requests get rejected

v1.0.2:

  • Add RequiredFormFileValidationFilter to support checking for [Required] parameters of type IFormFile on controller actions
  • .NETStandard 1.3
    • NETStandard.Library (>= 1.6.1)
    • Newtonsoft.Json (>= 12.0.2)
    • System.ComponentModel.Annotations (>= 4.5.0)
  • .NETStandard 2.0
    • Newtonsoft.Json (>= 12.0.2)
    • System.ComponentModel.Annotations (>= 4.5.0)
  • .NETStandard 2.1
    • Newtonsoft.Json (>= 12.0.2)
    • System.ComponentModel.Annotations (>= 4.5.0)
  • .NETStandard 1.3: 1.3.0.0
  • .NETStandard 2.0: 2.0.0.0
  • .NETStandard 2.1: 2.1.0.0

Owners

Georg Dangl

Authors

Georg Dangl

Project URL

https://github.com/GeorgDangl/Dangl.Data.Shared

License

Unknown

Info

408 total downloads
4 downloads for version 1.6.0-beta0006
Download (26.15 KB)
Found on the current feed only

Package history

Version Size Last updated Downloads Mirrored?
2.5.2 24.76 KB Sun, 08 Dec 2024 23:19:59 GMT 0
2.5.1 24.73 KB Fri, 25 Oct 2024 22:18:57 GMT 0
2.5.0 24.69 KB Tue, 26 Dec 2023 23:19:34 GMT 5
2.4.0 24.6 KB Mon, 16 Oct 2023 22:16:57 GMT 4
2.3.0 24.55 KB Mon, 25 Sep 2023 22:16:03 GMT 4
2.2.0 24.23 KB Thu, 21 Sep 2023 10:55:24 GMT 4
2.2.0-beta0021 24.04 KB Wed, 22 Jun 2022 19:51:29 GMT 4
2.2.0-beta0017 24.04 KB Wed, 22 Jun 2022 19:36:59 GMT 4
2.1.2-pullrequest0004-0009 24.08 KB Wed, 22 Jun 2022 15:30:21 GMT 4
2.1.2-beta0010 24.02 KB Wed, 22 Jun 2022 19:26:21 GMT 4
2.1.2-beta0008 24.01 KB Wed, 22 Sep 2021 07:00:40 GMT 5
2.1.2-beta0007 24.03 KB Wed, 22 Sep 2021 06:59:18 GMT 5
2.1.2-beta0006 24.01 KB Wed, 22 Sep 2021 06:58:20 GMT 4
2.1.2-beta0003 24.03 KB Fri, 17 Sep 2021 12:54:06 GMT 5
2.1.2-beta0002 24.03 KB Fri, 30 Jul 2021 11:52:19 GMT 4
2.1.1 23.98 KB Mon, 05 Jul 2021 23:03:22 GMT 5
2.1.1-beta0001 24.03 KB Mon, 05 Jul 2021 14:04:36 GMT 4
2.1.0 23.9 KB Sun, 13 Jun 2021 12:18:39 GMT 4
2.1.0-beta0001 23.95 KB Sun, 13 Jun 2021 12:16:24 GMT 5
2.0.0 23.84 KB Thu, 20 May 2021 12:27:14 GMT 5
2.0.0-beta0009 23.88 KB Thu, 20 May 2021 12:09:49 GMT 4
2.0.0-beta0008 23.89 KB Thu, 20 May 2021 12:04:58 GMT 4
1.9.1-beta0005 23.9 KB Thu, 20 May 2021 12:00:43 GMT 5
1.9.1-beta0001 29.43 KB Thu, 13 May 2021 18:48:50 GMT 5
1.9.0 29.39 KB Tue, 26 Jan 2021 21:56:56 GMT 5
1.9.0-beta0001 29.43 KB Tue, 26 Jan 2021 21:54:37 GMT 5
1.8.0 28.56 KB Tue, 26 Jan 2021 21:38:40 GMT 5
1.8.0-beta0005 28.62 KB Tue, 26 Jan 2021 21:34:43 GMT 5
1.7.1-beta0003 28.55 KB Tue, 26 Jan 2021 21:31:52 GMT 4
1.7.0 26.7 KB Wed, 06 Jan 2021 11:53:32 GMT 5
1.7.0-beta0006 26.76 KB Wed, 06 Jan 2021 11:46:46 GMT 5
1.6.0 26.09 KB Fri, 10 Jul 2020 18:28:17 GMT 4
1.6.0-beta0006 26.15 KB Fri, 10 Jul 2020 16:10:07 GMT 4
1.6.0-beta0005 26.13 KB Fri, 10 Jul 2020 13:05:18 GMT 4
1.5.1-beta0003 23.21 KB Sun, 14 Jun 2020 19:25:50 GMT 4
1.5.1-beta0002 23.2 KB Sun, 14 Jun 2020 12:31:27 GMT 5
1.5.0 23.16 KB Tue, 09 Jun 2020 20:48:49 GMT 5
1.5.0-beta0001 23.2 KB Tue, 09 Jun 2020 20:13:10 GMT 4
1.4.0 23.15 KB Sun, 13 Oct 2019 19:26:26 GMT 4
1.4.0-beta0006 23.19 KB Fri, 11 Oct 2019 23:15:50 GMT 4
1.4.0-beta0005 23.17 KB Fri, 11 Oct 2019 23:11:07 GMT 5
1.3.2-beta0002 16.37 KB Thu, 03 Oct 2019 08:58:59 GMT 5
1.3.2-beta0001 16.39 KB Wed, 02 Oct 2019 20:36:31 GMT 4
1.3.1 16.34 KB Mon, 26 Aug 2019 21:33:12 GMT 4
1.3.1-beta0001 16.37 KB Mon, 26 Aug 2019 21:29:42 GMT 5
1.3.0 15.97 KB Tue, 06 Aug 2019 10:17:11 GMT 4
1.3.0-beta0006 16.02 KB Tue, 06 Aug 2019 10:13:58 GMT 5
1.2.1-beta0004 15.11 KB Sun, 07 Jul 2019 19:03:12 GMT 4
1.2.1-beta0001 15.09 KB Thu, 04 Apr 2019 20:01:27 GMT 5
1.2.0 15.07 KB Wed, 13 Mar 2019 23:09:07 GMT 4
1.2.0-beta0004 15.1 KB Wed, 13 Mar 2019 23:01:45 GMT 5
1.1.2-beta0001 13.39 KB Sat, 02 Mar 2019 12:35:51 GMT 5
1.1.1 13.33 KB Wed, 06 Feb 2019 18:09:38 GMT 5
1.1.1-beta0003 13.38 KB Wed, 06 Feb 2019 17:08:27 GMT 5
1.1.1-beta0002 13.3 KB Fri, 01 Feb 2019 19:10:33 GMT 4
1.1.0 13.25 KB Sun, 20 Jan 2019 23:52:08 GMT 5
1.1.0-beta0013 13.3 KB Sun, 20 Jan 2019 23:17:42 GMT 5
1.1.0-beta0012 13.22 KB Sun, 20 Jan 2019 22:50:38 GMT 5
1.1.0-beta0011 13.29 KB Sun, 20 Jan 2019 22:21:38 GMT 4
1.1.0-beta0010 13.22 KB Sun, 20 Jan 2019 22:03:53 GMT 5
1.1.0-beta0009 13.22 KB Sun, 20 Jan 2019 21:56:08 GMT 4
1.1.0-beta0005 13.17 KB Sun, 20 Jan 2019 21:00:36 GMT 5
1.0.11-beta0001 13.17 KB Thu, 03 Jan 2019 15:07:45 GMT 5
1.0.10 13.13 KB Tue, 07 Aug 2018 22:25:26 GMT 7
1.0.10-beta0002 13.17 KB Tue, 07 Aug 2018 22:22:10 GMT 5
1.0.9 13.1 KB Wed, 18 Jul 2018 12:22:44 GMT 4
1.0.9-beta0001 13.13 KB Wed, 18 Jul 2018 12:16:02 GMT 5
1.0.8 13.02 KB Mon, 09 Jul 2018 22:08:39 GMT 5
1.0.8-beta0010 13.07 KB Mon, 09 Jul 2018 22:04:30 GMT 5
1.0.8-beta0009 13.06 KB Mon, 09 Jul 2018 21:48:55 GMT 4
1.0.8-beta0008 13.07 KB Mon, 09 Jul 2018 21:43:43 GMT 5
1.0.8-beta0007 13.05 KB Mon, 09 Jul 2018 20:04:46 GMT 6
1.0.8-beta0006 13.07 KB Mon, 09 Jul 2018 19:42:49 GMT 4
1.0.8-beta0003 13.03 KB Tue, 19 Jun 2018 16:20:24 GMT 5
1.0.8-beta0002 13.02 KB Wed, 13 Jun 2018 20:10:19 GMT 5
1.0.8-beta0001 13.03 KB Sun, 10 Jun 2018 17:47:50 GMT 5
1.0.7 12.98 KB Sun, 10 Jun 2018 17:21:52 GMT 4
1.0.7-beta0010 13.03 KB Sun, 10 Jun 2018 17:16:50 GMT 4
1.0.7-beta0009 13.03 KB Sun, 10 Jun 2018 17:10:58 GMT 5
1.0.7-beta0008 13.02 KB Sun, 10 Jun 2018 17:06:25 GMT 4
1.0.7-beta0002 13.05 KB Sun, 10 Jun 2018 12:25:22 GMT 5
1.0.7-beta0001 12.94 KB Fri, 01 Jun 2018 21:56:41 GMT 5
1.0.6 12.91 KB Fri, 01 Jun 2018 21:53:31 GMT 5
1.0.6-beta0001 12.95 KB Fri, 01 Jun 2018 21:48:54 GMT 5
1.0.5 12.88 KB Fri, 01 Jun 2018 20:15:30 GMT 4
1.0.5-beta0002 12.92 KB Fri, 01 Jun 2018 19:59:33 GMT 5
1.0.5-beta0001 12.22 KB Wed, 02 May 2018 21:38:26 GMT 4
1.0.4 12.19 KB Wed, 02 May 2018 21:11:49 GMT 5
1.0.4-beta0005 12.23 KB Wed, 02 May 2018 21:08:09 GMT 4
1.0.4-beta0004 12.23 KB Wed, 02 May 2018 21:06:55 GMT 4
1.0.4-beta0002 12.24 KB Wed, 02 May 2018 21:04:19 GMT 4