Skip to content

Instantly share code, notes, and snippets.

@jbreuer
Created April 4, 2024 15:01
Show Gist options
  • Save jbreuer/83f419c259153f5e546dd0d0e32ab5b6 to your computer and use it in GitHub Desktop.
Save jbreuer/83f419c259153f5e546dd0d0e32ab5b6 to your computer and use it in GitHub Desktop.
Umbraco UI Builder + Web API
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using NPoco;
using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations;
using Umbraco.Cms.Infrastructure.Scoping;
using Umbraco.Cms.Web.Common.Controllers;
namespace UmbracoProject;
public class FeedbackController : UmbracoApiController
{
private readonly IScopeProvider _scopeProvider;
public FeedbackController(IScopeProvider scopeProvider)
{
_scopeProvider = scopeProvider;
}
[HttpGet]
public IEnumerable<FeedbackDto> GetFeedback()
{
using var scope = _scopeProvider.CreateScope();
var queryResults = scope.Database.Fetch<FeedbackDto>("SELECT * FROM Feedback");
scope.Complete();
return queryResults;
}
[HttpPost]
public void InsertFeedback([FromBody] FeedbackRequest feedbackRequest)
{
var feedbackDto = new FeedbackDto
{
Name = feedbackRequest.FullName,
Email = feedbackRequest.Email,
Type = feedbackRequest.FeedbackType,
Message = feedbackRequest.Feedback
};
using var scope = _scopeProvider.CreateScope();
scope.Database.Insert<FeedbackDto>(feedbackDto);
scope.Complete();
}
}
public class FeedbackRequest
{
[JsonProperty("Full name")]
public string FullName { get; set; }
public string Email { get; set; }
public string FeedbackType { get; set; }
public string Feedback { get; set; }
}
[TableName("Feedback")]
[PrimaryKey("Id", AutoIncrement = true)]
[ExplicitColumns]
public class FeedbackDto
{
[PrimaryKeyColumn(AutoIncrement = true, IdentitySeed = 1)]
[Column("Id")]
public int Id { get; set; }
[Column("Name")]
public required string Name { get; set; }
[Column("Email")]
public required string Email { get; set; }
[Column("Type")]
public required string Type { get; set; }
[Column("Message")]
[SpecialDbType(SpecialDbTypes.NVARCHARMAX)]
public string Message { get; set; }
}
using NPoco;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Migrations;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Migrations;
using Umbraco.Cms.Infrastructure.Migrations.Upgrade;
using Umbraco.Cms.Infrastructure.Persistence.DatabaseAnnotations;
namespace UmbracoProject;
public class RunFeedbackMigration : INotificationHandler<UmbracoApplicationStartingNotification>
{
private readonly IMigrationPlanExecutor _migrationPlanExecutor;
private readonly ICoreScopeProvider _coreScopeProvider;
private readonly IKeyValueService _keyValueService;
private readonly IRuntimeState _runtimeState;
public RunFeedbackMigration(
ICoreScopeProvider coreScopeProvider,
IMigrationPlanExecutor migrationPlanExecutor,
IKeyValueService keyValueService,
IRuntimeState runtimeState)
{
_migrationPlanExecutor = migrationPlanExecutor;
_coreScopeProvider = coreScopeProvider;
_keyValueService = keyValueService;
_runtimeState = runtimeState;
}
public void Handle(UmbracoApplicationStartingNotification notification)
{
if (_runtimeState.Level < RuntimeLevel.Run)
{
return;
}
var migrationPlan = new MigrationPlan("Feedback");
migrationPlan.From(string.Empty)
.To<AddFeedbackTable>("feedback-db");
var upgrader = new Upgrader(migrationPlan);
upgrader.Execute(
_migrationPlanExecutor,
_coreScopeProvider,
_keyValueService);
}
}
public class FeedbackComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.AddNotificationHandler<UmbracoApplicationStartingNotification, RunFeedbackMigration>();
}
}
public class AddFeedbackTable : MigrationBase
{
public AddFeedbackTable(IMigrationContext context) : base(context)
{
}
protected override void Migrate()
{
Logger.LogDebug("Running migration {MigrationStep}", "AddFeedbackTable");
if (TableExists("Feedback") == false)
{
Create.Table<FeedbackSchema>().Do();
}
else
{
Logger.LogDebug("The database table {DbTable} already exists, skipping", "Feedback");
}
}
[TableName("Feedback")]
[PrimaryKey("Id", AutoIncrement = true)]
[ExplicitColumns]
public class FeedbackSchema
{
[PrimaryKeyColumn(AutoIncrement = true, IdentitySeed = 1)]
[Column("Id")]
public int Id { get; set; }
[Column("Name")]
public required string Name { get; set; }
[Column("Email")]
public required string Email { get; set; }
[Column("Type")]
public required string Type { get; set; }
[Column("Message")]
[SpecialDbType(SpecialDbTypes.NVARCHARMAX)]
public string Message { get; set; }
}
}
using Umbraco.UIBuilder.Extensions;
namespace UmbracoProject
{
public class Startup
{
private readonly IWebHostEnvironment _env;
private readonly IConfiguration _config;
/// <summary>
/// Initializes a new instance of the <see cref="Startup" /> class.
/// </summary>
/// <param name="webHostEnvironment">The web hosting environment.</param>
/// <param name="config">The configuration.</param>
/// <remarks>
/// Only a few services are possible to be injected here https://github.com/dotnet/aspnetcore/issues/9337.
/// </remarks>
public Startup(IWebHostEnvironment webHostEnvironment, IConfiguration config)
{
_env = webHostEnvironment ?? throw new ArgumentNullException(nameof(webHostEnvironment));
_config = config ?? throw new ArgumentNullException(nameof(config));
}
/// <summary>
/// Configures the services.
/// </summary>
/// <param name="services">The services.</param>
/// <remarks>
/// This method gets called by the runtime. Use this method to add services to the container.
/// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940.
/// </remarks>
public void ConfigureServices(IServiceCollection services)
{
services.AddUmbraco(_env, _config)
.AddBackOffice()
.AddWebsite()
.AddDeliveryApi()
.AddComposers()
.AddUIBuilder(cfg => {
cfg.AddSectionAfter("media", "Repositories", sectionConfig => sectionConfig
.Tree(treeConfig => treeConfig
.AddCollection<FeedbackDto>(x => x.Id, "Feedback", "Feedback", "A feedback entity", "icon-forms-stackoverflow", "icon-forms-stackoverflow", collectionConfig => collectionConfig
.SetNameProperty(p => p.Name)
.ListView(listViewConfig => listViewConfig
.AddField(p => p.Email)
)
.Editor(editorConfig => editorConfig
.AddTab("General", tabConfig => tabConfig
.AddFieldset("General", fieldsetConfig => fieldsetConfig
.AddField(p => p.Type)
.AddField(p => p.Email).SetValidationRegex("[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+")
.AddField(p => p.Message).SetDataType("Textarea")
)
)
)
)
)
);
})
.Build();
}
/// <summary>
/// Configures the application.
/// </summary>
/// <param name="app">The application builder.</param>
/// <param name="env">The web hosting environment.</param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseUmbraco()
.WithMiddleware(u =>
{
u.UseBackOffice();
u.UseWebsite();
})
.WithEndpoints(u =>
{
u.UseInstallerEndpoints();
u.UseBackOfficeEndpoints();
u.UseWebsiteEndpoints();
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment