Skip to content

Commit

Permalink
Various minor fixes (#38)
Browse files Browse the repository at this point in the history
* add PineBlogViewDataAsyncPageFilter
* Get the connection string by the connextion name
  • Loading branch information
petervandenhout authored Aug 11, 2019
1 parent 2cdd9e8 commit 4d0caa6
Show file tree
Hide file tree
Showing 25 changed files with 127 additions and 83 deletions.
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ steps:
# Release: triggered by a version tag
- task: DotNetCoreCLI@2
displayName: NuGet Pack Opw.PineBlog.Core
# condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'))
inputs:
command: pack
packagesToPack: '**/Opw.PineBlog.Core.csproj'
Expand Down
5 changes: 2 additions & 3 deletions ref/Opw.PineBlog/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@ public static class ServiceCollectionExtensions
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="configuration">The application configuration properties.</param>
/// <param name="connectionString">The connectionString.</param>
/// <returns>The original services object.</returns>
public static IServiceCollection AddPineBlog(this IServiceCollection services, IConfiguration configuration, string connectionString)
public static IServiceCollection AddPineBlog(this IServiceCollection services, IConfiguration configuration)
{
services.AddPineBlogCore(configuration);
services.AddPineBlogEntityFrameworkCore(connectionString);
services.AddPineBlogEntityFrameworkCore(configuration);

return services;
}
Expand Down
3 changes: 1 addition & 2 deletions samples/Opw.PineBlog.Sample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ public void ConfigureServices(IServiceCollection services)
.AddCookie();

// TODO: combine with AddPineBlogRazorPages?
var connectionString = Configuration.GetConnectionString("DefaultConnection");
services.AddPineBlog(Configuration, connectionString);
services.AddPineBlog(Configuration);
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand Down
1 change: 1 addition & 0 deletions samples/Opw.PineBlog.Sample/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"CoverLink": "http://pixeljoint.com/pixelart/94359.htm",
"ItemsPerPage": 2,
"CreateAndSeedDatabases": true,
"ConnectionStringName": "DefaultConnection",
"AzureStorageConnectionString": "UseDevelopmentStorage=true",
"AzureStorageBlobContainerName": "pineblog",
"FileBaseUrl": "http://127.0.0.1:10000/devstoreaccount1"
Expand Down
2 changes: 0 additions & 2 deletions src/Opw.EntityFrameworkCore/DbContextConfigurer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Storage;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Text;

namespace Opw.EntityFrameworkCore
{
Expand Down
5 changes: 2 additions & 3 deletions src/Opw.PineBlog.Abstractions/PineBlogOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@ public class PineBlogOptions
public string FileBaseUrl { get; set; }

/// <summary>
/// Database connection string.
/// Database connection string name.
/// </summary>
// TODO: use this connection string
public string ConnectionString { get; set; }
public string ConnectionStringName { get; set; }

/// <summary>
/// Azure storage connection string.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Opw.EntityFrameworkCore;

namespace Opw.PineBlog.EntityFrameworkCore
Expand All @@ -12,11 +14,16 @@ public static class ServiceCollectionExtensions
/// Adds PineBlog Entity Framework Core services to the specified services collection.
/// </summary>
/// <param name="services">The services available in the application.</param>
/// <param name="connectionString">The connectionString.</param>
/// <param name="configuration">The application configuration properties.</param>
/// <returns>The original services object.</returns>
public static IServiceCollection AddPineBlogEntityFrameworkCore(this IServiceCollection services, string connectionString)
public static IServiceCollection AddPineBlogEntityFrameworkCore(this IServiceCollection services, IConfiguration configuration)
{
services.AddDbContextPool<IBlogEntityDbContext, BlogEntityDbContext>(options => DbContextConfigurer.Configure(options, connectionString));
services.AddDbContextPool<IBlogEntityDbContext, BlogEntityDbContext>((provider, options) =>
{
var blogOptions = provider.GetRequiredService<IOptions<PineBlogOptions>>();
var connectionString = configuration.GetConnectionString(blogOptions.Value.ConnectionStringName);
DbContextConfigurer.Configure(options, connectionString);
});

return services;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public class AddPostModel : PageModelBase<AddPostModel>
[BindProperty]
public AddPostCommand Post { get; set; }

public AddPostModel(IMediator mediator, IOptions<PineBlogOptions> options, ILogger<AddPostModel> logger)
: base(options, logger)
public AddPostModel(IMediator mediator, ILogger<AddPostModel> logger)
: base(logger)
{
_mediator = mediator;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Opw.PineBlog.RazorPages/Areas/Admin/Pages/Posts.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public class PostsModel : PageModelBase<PostsModel>
public Pager Pager { get; private set; }
public IEnumerable<Post> Posts { get; set; }

public PostsModel(IMediator mediator, IOptions<PineBlogOptions> options, ILogger<PostsModel> logger)
: base(options, logger)
public PostsModel(IMediator mediator, ILogger<PostsModel> logger)
: base(logger)
{
_mediator = mediator;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<footer class="footer copy">
<div class="container d-lg-flex text-center text-lg-left">
<p><a href="https://github.com/ofpinewood/pineblog">PineBlog</a> &copy; @DateTime.Now.Year Of Pine Wood (@ViewData["ApplicationVersion"])</p>
<p>
Powered by <a href="https://github.com/ofpinewood/pineblog">PineBlog</a>
&copy; @DateTime.Now.Year <a href="https://github.com/ofpinewood">Of Pine Wood</a>
(@ViewData["PineBlogVersion"])
</p>
</div>
</footer>
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public class UpdatePostModel : PageModelBase<UpdatePostModel>
[BindProperty]
public UpdatePostCommand Post { get; set; }

public UpdatePostModel(IMediator mediator, IOptions<PineBlogOptions> options, ILogger<UpdatePostModel> logger)
: base(options, logger)
public UpdatePostModel(IMediator mediator, ILogger<UpdatePostModel> logger)
: base(logger)
{
_mediator = mediator;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Opw.PineBlog.RazorPages/Areas/Blog/Pages/Index.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public class IndexModel : PageModelBase<IndexModel>
[ViewData]
public string Title { get; private set; }

public IndexModel(IMediator mediator, IOptions<PineBlogOptions> options, ILogger<IndexModel> logger)
: base(options, logger)
public IndexModel(IMediator mediator, ILogger<IndexModel> logger)
: base(logger)
{
_mediator = mediator;
}
Expand Down
9 changes: 6 additions & 3 deletions src/Opw.PineBlog.RazorPages/Areas/Blog/Pages/Post.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ public class PostModel : PageModelBase<PostModel>
private readonly IMediator _mediator;

public PineBlog.Models.PostModel Post { get; set; }

public PostModel(IMediator mediator, IOptions<PineBlogOptions> options, ILogger<PostModel> logger)
: base(options, logger)

[ViewData]
public string Title { get; private set; }

public PostModel(IMediator mediator, ILogger<PostModel> logger)
: base(logger)
{
_mediator = mediator;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<footer class="footer copy">
<div class="container d-lg-flex text-center text-lg-left">
<p><a href="https://github.com/ofpinewood/pineblog">PineBlog</a> &copy; @DateTime.Now.Year Of Pine Wood (@ViewData["ApplicationVersion"])</p>
<p>
Powered by <a href="https://github.com/ofpinewood/pineblog">PineBlog</a>
&copy; @DateTime.Now.Year <a href="https://github.com/ofpinewood">Of Pine Wood</a>
(@ViewData["PineBlogVersion"])
</p>
<div class="ml-auto">
@if (User.Identity.IsAuthenticated)
{
Expand Down
8 changes: 8 additions & 0 deletions src/Opw.PineBlog.RazorPages/MvcCoreBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ public static IMvcCoreBuilder AddPineBlogRazorPages(this IMvcCoreBuilder builder
option.Conventions.AuthorizeAreaFolder("Admin", "/");
option.Conventions.AddAreaPageRoute("Blog", "/Post", "blog/{*slug}");
});
builder.AddMvcOptions(options =>
{
options.Filters.Add<PineBlogViewDataAsyncPageFilter>();
});
builder.AddFluentValidation();

return builder;
Expand All @@ -41,6 +45,10 @@ public static IMvcBuilder AddPineBlogRazorPages(this IMvcBuilder builder)
option.Conventions.AuthorizeAreaFolder("Admin", "/");
option.Conventions.AddAreaPageRoute("Blog", "/Post", "blog/{*slug}");
});
builder.AddMvcOptions(options =>
{
options.Filters.Add<PineBlogViewDataAsyncPageFilter>();
});
builder.AddFluentValidation();

return builder;
Expand Down
20 changes: 1 addition & 19 deletions src/Opw.PineBlog.RazorPages/PageModelBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
Expand All @@ -23,30 +22,13 @@ public abstract class PageModelBase<TPageModel> : PageModel
/// </summary>
protected readonly ILogger Logger;

/// <summary>
/// Page title.
/// </summary>
[ViewData]
public string Title { get; protected set; }

/// <summary>
/// The version of the current running code.
/// </summary>
[ViewData]
public string ApplicationVersion { get; }

/// <summary>
/// Implementation of PageModelBase.
/// </summary>
/// <param name="options">Blog options.</param>
/// <param name="logger">Logger.</param>
public PageModelBase(IOptions<PineBlogOptions> options, ILogger<TPageModel> logger)
public PageModelBase(ILogger<TPageModel> logger)
{
Options = options;
Logger = logger;

ApplicationVersion = Options.Value.Version;
Title = Options.Value.Title;
}

/// <summary>
Expand Down
57 changes: 57 additions & 0 deletions src/Opw.PineBlog.RazorPages/PineBlogViewDataAsyncResultFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;

namespace Opw.PineBlog.RazorPages
{
/// <summary>
/// A filter that asynchronously sets the ViewData of a page.
/// </summary>
public class PineBlogViewDataAsyncPageFilter : IAsyncPageFilter
{
private readonly IOptions<PineBlogOptions> _options;

/// <summary>
/// Implementation of PineBlogViewDataAsyncPageFilter.
/// </summary>
/// <param name="options">Blog options.</param>
public PineBlogViewDataAsyncPageFilter(IOptions<PineBlogOptions> options)
{
_options = options;
}

/// <summary>
/// Called asynchronously before the handler method is invoked, after model binding is complete.
/// </summary>
/// <param name="context">The <see cref="PageHandlerExecutingContext" />.</param>
/// <param name="next">
/// The <see cref="PageHandlerExecutionDelegate" />. Invoked to execute the next page filter or the handler method itself.
/// </param>
/// <returns>A <see cref="Task" /> that on completion indicates the filter has executed.</returns>
public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
{
var pageModel = context.HandlerInstance as PageModel;
if (pageModel == null)
{
await next();
return;
}

pageModel.ViewData["PineBlogVersion"] = _options.Value.Version;
pageModel.ViewData["Title"] = _options.Value.Title;

await next();
}

/// <summary>
/// Called asynchronously after the handler method has been selected, but before model binding occurs.
/// </summary>
/// <param name="context">The <see cref="PageHandlerSelectedContext" />.</param>
/// <returns>A <see cref="Task" /> that on completion indicates the filter has executed.</returns>
public async Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
{
await Task.CompletedTask;
}
}
}
4 changes: 0 additions & 4 deletions src/build.cmd

This file was deleted.

25 changes: 4 additions & 21 deletions tests/Opw.PineBlog.Core.Tests/MediatRTestsBase.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
using MediatR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Opw.PineBlog.EntityFrameworkCore;
using Opw.PineBlog.Files.Azure;
using Opw.PineBlog.Models;
using Opw.PineBlog.Posts;
using System;
using System.Threading;

namespace Opw.PineBlog
{
Expand All @@ -25,26 +21,13 @@ public MediatRTestsBase()
.AddJsonFile("appsettings.json")
.Build();

// create a new in-memory database for each test
configuration.GetSection("ConnectionStrings").GetSection("DefaultConnection").Value = $"Server=inMemory; Database=pineblog-tests-{DateTime.UtcNow.Ticks};";

Services = new ServiceCollection();
Services.AddMediatR(typeof(AddPostCommand).Assembly);
Services.AddPineBlogCore(configuration);
Services.AddPineBlogEntityFrameworkCore($"Server=inMemory; Database=opw-db-{DateTime.UtcNow.Ticks};");

//Services.AddTransient((_) => {
// var mock = new Mock<IRequestHandler<UploadAzureBlobCommand, Result<string>>>();
// mock.Setup(h => h.Handle(It.IsAny<UploadAzureBlobCommand>(), It.IsAny<CancellationToken>()))
// .ReturnsAsync((UploadAzureBlobCommand request, CancellationToken __) =>
// Result<string>.Success($"http://azureblobstorage/pineblog-tests/{request.TargetPath}/{request.FileName}"));
// return mock.Object;
//});

//Services.AddTransient((_) => {
// var mock = new Mock<IRequestHandler<GetPagedAzureBlobListQuery, Result<FileListModel>>>();
// mock.Setup(h => h.Handle(It.IsAny<GetPagedAzureBlobListQuery>(), It.IsAny<CancellationToken>()))
// .ReturnsAsync((GetPagedAzureBlobListQuery request, CancellationToken __) =>
// Result<FileListModel>.Success(new FileListModel { Pager = request.Pager }));
// return mock.Object;
//});
Services.AddPineBlogEntityFrameworkCore(configuration);
}
}
}
4 changes: 4 additions & 0 deletions tests/Opw.PineBlog.Core.Tests/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
{
"ConnectionStrings": {
"DefaultConnection": "Server=inMemory; Database=pineblog-db;"
},
"PineBlogOptions": {
"Title": "Title from configuration",
"PagingUrlPartFormat": "page={0}",
"CategoryUrlPartFormat": "category={0}",
"ItemsPerPage": 3,
"ConnectionStringName": "DefaultConnection",
"AzureStorageConnectionString": "UseDevelopmentStorage=true",
"AzureStorageBlobContainerName": "pineblog-tests",
"FileBaseUrl": "http://127.0.0.1:10000/devstoreaccount1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public async Task OnGet_Should_SetEmptyAddPostCommand()
var httpContext = new DefaultHttpContext();
var pageContext = GetPageContext(httpContext);

var pageModel = new AddPostModel(mediaterMock.Object, OptionsMock.Object, loggerMock.Object)
var pageModel = new AddPostModel(mediaterMock.Object, loggerMock.Object)
{
PageContext = pageContext.Item1,
TempData = GetTempDataDictionary(httpContext),
Expand All @@ -53,7 +53,7 @@ public async Task OnPostAsync_Should_ReturnRedirectToPageResult()
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, "user@example.com") }));
var pageContext = GetPageContext(httpContext);

var pageModel = new AddPostModel(mediaterMock.Object, OptionsMock.Object, loggerMock.Object)
var pageModel = new AddPostModel(mediaterMock.Object, loggerMock.Object)
{
PageContext = pageContext.Item1,
TempData = GetTempDataDictionary(httpContext),
Expand Down Expand Up @@ -84,7 +84,7 @@ public async Task OnPostAsync_Should_SetUserNameOfTheCurrentUser()
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, "user@example.com") }));
var pageContext = GetPageContext(httpContext);

var pageModel = new AddPostModel(mediaterMock.Object, OptionsMock.Object, loggerMock.Object)
var pageModel = new AddPostModel(mediaterMock.Object, loggerMock.Object)
{
PageContext = pageContext.Item1,
TempData = GetTempDataDictionary(httpContext),
Expand Down Expand Up @@ -116,7 +116,7 @@ public async Task OnPostAsync_Should_SetModelStateError_OnAddPostCommandFail()
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, "user@example.com") }));
var pageContext = GetPageContext(httpContext);

var pageModel = new AddPostModel(mediaterMock.Object, OptionsMock.Object, loggerMock.Object)
var pageModel = new AddPostModel(mediaterMock.Object, loggerMock.Object)
{
PageContext = pageContext.Item1,
TempData = GetTempDataDictionary(httpContext),
Expand Down
Loading

0 comments on commit 4d0caa6

Please sign in to comment.