Skip to content
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

Closed
wants to merge 8 commits into from

Conversation

jersiovic
Copy link
Contributor

@jersiovic jersiovic commented Mar 19, 2017

#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.

@jersiovic jersiovic changed the title #495 Added RecipeExtraParams to SetupContext for simplify Custom Setup #495 Added RecipeExtraParams to SetupContext for simplifying Custom Setup Mar 19, 2017
@@ -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; }
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

@sebastienros sebastienros force-pushed the master branch 2 times, most recently from 37f0cda to 081a307 Compare April 6, 2017 02:35
@jersiovic
Copy link
Contributor Author

jersiovic commented Apr 12, 2017

@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.
For use cases where it is ok to perform validation of extra parameters only in client side it is an useful feature.

}
@{
var setupViewModel = Model.SetupViewModel as SetupViewModel;
AddPrefixToModelState(nameof(SetupViewModel));
Copy link
Contributor Author

@jersiovic jersiovic Apr 12, 2017

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

Copy link
Contributor Author

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

Copy link
Member

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; }
Copy link
Contributor Author

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.

@jersiovic
Copy link
Contributor Author

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.

@jersiovic
Copy link
Contributor Author

Checks based on travis build fails on mac, but error doesn't seems to be related with nothing in this PR

@sebastienros
Copy link
Member

The mac build on travis is always failing, independent from your PR


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)
Copy link
Contributor Author

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

@jersiovic
Copy link
Contributor Author

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?

Copy link
Member

@sebastienros sebastienros left a 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));
Copy link
Member

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>
Copy link
Member

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>();
Copy link
Member

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>();
Copy link
Member

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)
Copy link
Member

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.

Copy link
Member

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.

@sebastienros
Copy link
Member

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 IFile that give access to a list of recipes. This module would be part of the Default features.

@jersiovic
Copy link
Contributor Author

Thank you for the review.
Till now I was using my own setup recipe stored in my custom module and it was detected without problems. I will check that it doesn't work as it did before when I rebase our branch o top of master.

@jersiovic
Copy link
Contributor Author

Confirmed, setup recipes in other modules are loaded automatically by Orchard.
image

@jersiovic
Copy link
Contributor Author

jersiovic commented Apr 17, 2017

@sebastienros said:

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.

Yes, it is only for setup. You only need to override setup shape, not anything else.

Have you used this branch already and checked it worked as expected?

I tested it partially, I checked valid values were provided to the recipe.
But after hearing that you agree with this PR I'm going to test it in our web api project based on Orchard 2 to be sure everything fits properly. Till now in that project we had modified Orchard.Setup module view and controller to have a custom setup, so it will be a good test.

@jersiovic
Copy link
Contributor Author

I'm able to override setup shape only if I put the custom setup shape in SafeMode theme and initializin OrchardCms with SafeMode module: services.AddOrchardCms("SafeMode");. But if I use a regular module it doesn't work. Is there a way of overriding a shape invoked in another module from a module that is not a theme?

@@ -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);
Copy link
Contributor Author

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.

@jersiovic jersiovic changed the title #495 Added RecipeExtraParams to SetupContext for simplifying Custom Setup #495 Added RecipeExtraParams to SetupContext for simplifying Custom Setup. NOT MERGE WIP Apr 19, 2017
@jersiovic
Copy link
Contributor Author

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

@jersiovic jersiovic closed this Apr 20, 2017
@Jetski5822 Jetski5822 deleted the #495customSetup branch June 20, 2017 07:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants