-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#495 Added RecipeExtraParams to SetupContext for simplifying Custom Setup. NOT MERGE WIP #624
Conversation
@@ -12,6 +12,7 @@ public class SetupContext | |||
public string DatabaseProvider { get; set; } | |||
public string DatabaseConnectionString { get; set; } | |||
public string DatabaseTablePrefix { get; set; } | |||
public IDictionary<string, string> RecipeExtraParams { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why a dictionary, didn't the anonymous object work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, in the case anyone want to provide its own custom controller you are right, the same could be done with an anonymous.
But this morning I was thinking we can change current setup controller to act in a generic way passing all the key/values available in form posted to RecipeExtraParams (except those named as the properties in SetupContext).
Doing that in many cases we won't need to have our own controller. So, to have a custom setup we would need only a new view. That connot be donde with an anonymous type as far as I know.
Next step would be we could add a custom shape to our theme that would replace custom setup form, then in many cases we won't need an extra module to have a custom setup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, in the case anyone want to provide its own custom controller you are right, the same could be done with an anonymous.
But this morning I was thinking we can change current setup controller to act in a generic way passing all the key/values available in form posted to RecipeExtraParams (except those named as the properties in SetupContext).
Doing that in many cases we won't need to have our own controller. So, to have a custom setup we would need only a new view. That cannoy be done with an anonymous type as far as I know.
Next step would be we could add a custom shape to our theme that would replace custom setup form, then in many cases we won't need an extra module to have a custom setup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, in the case anyone want to provide its own custom controller you are right, the same could be done with an anonymous.
But this morning I was thinking we can change current setup controller to act in a generic way passing all the key/values available in form posted to RecipeExtraParams (except those named as the properties in SetupContext).
Doing that in many cases we won't need to have our own controller. So, to have a custom setup we would need only a new view. That cannot be done with an anonymous type as far as I know.
Next step would be we could add a custom shape to our theme that would replace custom setup form, then in many cases we won't need an extra module to have a custom setup.
37f0cda
to
081a307
Compare
b8429e0
to
34c7691
Compare
@sebastienros on last commit I've added a setup shape and passed to the recipe parameters all the key values in RequestForm, in that way anyone can override default setup shape for passing extra parameters to the recipe reusing existing controller. |
} | ||
@{ | ||
var setupViewModel = Model.SetupViewModel as SetupViewModel; | ||
AddPrefixToModelState(nameof(SetupViewModel)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How shapes model is dynamic I need to rename ModelState keys to be able of continuing using asp-for
attributes for validating posted data
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of this hack do you agree if I change calls to AddModelError within Controller for adding nameof(SetupViewModel)
as Prefix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can have strongly typed Shapes in OrchardCore. Look at the drivers from the CMS module. If you can't find it I will grab an example for you.
@@ -12,7 +13,7 @@ public class SetupContext | |||
public string DatabaseProvider { get; set; } | |||
public string DatabaseConnectionString { get; set; } | |||
public string DatabaseTablePrefix { get; set; } | |||
public IDictionary<string, string> RecipeExtraParams { get; set; } | |||
public IDictionary<string, StringValues> RecipeExtraParams { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Request.Form stores data on StringValues that is why I replaced string per StringValues for not losing input data.
A future improvement for this feature could be to add a shape alternate for the setup with the name of the recipe selected. When the user changes the recipe the reload would be forced to load any specific shape for the selected recipe. |
Checks based on travis build fails on mac, but error doesn't seems to be related with nothing in this PR |
The mac build on travis is always failing, independent from your PR |
bdf62b1
to
5940a41
Compare
|
||
namespace Microsoft.Extensions.DependencyInjection | ||
{ | ||
public static class ServiceExtensions | ||
{ | ||
public static IServiceCollection AddOrchardCms(this IServiceCollection services) | ||
public static IServiceCollection AddOrchardCms(this IServiceCollection services, params string[] extraDefaultFeatureIds) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows to set featureIds to be loaded on startup of the root project.
For example if you provide an alternate Setup shape in your SafeMode theme that replaces default shape you should initialize Orchard calling services.AddOrchardCms("SafeMode");
on Startup
Please can you give me feedback related with this PR? Do you prefer I remove the hack done in setup shape for validation? What would be best solution in your opinión? Do we need to agree on design of this feature before merging it? Do you want a demo? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took some time to look at the changes and the goals here. It's a good start I think. I can't see any better way than providing a custom shape for now in terms of extensibility. And i assume it doesn't force the final application to have theming, it's just for setup.
Have you used this branch already and checked it worked as expected?
} | ||
@{ | ||
var setupViewModel = Model.SetupViewModel as SetupViewModel; | ||
AddPrefixToModelState(nameof(SetupViewModel)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can have strongly typed Shapes in OrchardCore. Look at the drivers from the CMS module. If you can't find it I will grab an example for you.
@@ -0,0 +1,2 @@ | |||
@inherits Orchard.DisplayManagement.Razor.RazorPage<TModel> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should keep this file in the Views folder (preparing for the future).
@@ -18,7 +19,7 @@ public ParametersMethodProvider(object environment) | |||
Name = "parameters", | |||
Method = serviceprovider => (Func<string, object>) (name => | |||
{ | |||
return environmentObject[name].Value<string>(); | |||
return environmentObject[name].Value<StringValues>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep strings.
DatabaseConnectionString = context.DatabaseConnectionString, | ||
DatabaseTablePrefix = context.DatabaseTablePrefix | ||
}); | ||
var recipeParams = context.RecipeExtraParams ?? new Dictionary<string,StringValues>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use strings only. Or even better, objects. But definitely not StringValues
@@ -128,7 +129,8 @@ public class SetupController : Controller | |||
AdminEmail = model.Email, | |||
AdminPassword = model.Password, | |||
Errors = new Dictionary<string, string>(), | |||
Recipe = selectedRecipe | |||
Recipe = selectedRecipe, | |||
RecipeExtraParams = Request.Form.ToDictionary(keyValue => keyValue.Key, keyValue => keyValue.Value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure it's a good idea to just take everything coming from the Form. Looks like a potential security issue to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There might not be a better way though, I will have to think about it.
Right now the setup recipes have to be in the Setup module. Maybe we should make this extensible and have the current recipes come from a CMS module. Something using DI could then resolve the |
Thank you for the review. |
@sebastienros said:
Yes, it is only for setup. You only need to override setup shape, not anything else.
I tested it partially, I checked valid values were provided to the recipe. |
I'm able to override setup shape only if I put the custom setup shape in SafeMode theme and initializin OrchardCms with SafeMode module: |
ae6ff89
to
f027e16
Compare
f027e16
to
0451d58
Compare
@@ -259,7 +259,7 @@ private void EvaluateJsonTree(IScriptingManager scriptingManager, JToken node) | |||
// Evaluate the expression while the result is another expression | |||
while (value.StartsWith("[") && value.EndsWith("]")) | |||
{ | |||
value = value.Trim('[', ']'); | |||
value = value.Substring(1, value.Length - 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sebastienros I replaced Trim because it caused a bug on expressions like this: "[js:parameters('extraSettings.Code')[0]]"
because it removes last two brackets instead of only ones causing an exception later when the expression is parsed.
I close this PR cause I didn't take into account that for returning posted data in postback when controller finds an error I need do things not very clean for binding those data on the setup shape controls. So the solution will be a bit hacky. It would be interesting me or other tries a less easy but more elegant approach based on #716 |
#495 issue asks for a setup wizard.
This PR replaces current setup view per a setup shape. In this way an user can override default setup shape with his own customized Setup shape adding the setup shape on a custom module enabled by default at startup.cs of the root project with
services.AddOrchardCms("ModuleOrThemeOverridingSetupShape");
.This PR also changes SetupController and SetupService to help to be reused with other shapes that provides extras parameters for a setup recipe. For doing that it adds to SetupContext a property called RecipeExtraParams of type IDictionary<string, StringValues> where our custom controller will put Request.Form keys and values.