I have an Otter job template for which I have defined a number of custom variables, some of which are marked as Required and some are not.
If I view previous executions of that job in /jobs/history
, there is a small (play) button icon against each execution, for which I believe the intention is to re-run any one particular execution with the variable prompts pre-populated with the previously-entered values for that execution.
If there were no custom variables defined on the template or, for that execution, if all the custom variables were populated with a value, clicking that button works as intended.
If, however, I did not set a value for one of the properties (i.e. it was left as an empty text box), clicking that button results in an HTTP/500 server error. The Diagnostic Centre page yields the following:
An error occurred in the web application: The given key 'MyCustomVariableName' was not present in the dictionary.
URL: http://xxxx:8626/jobs/from-template?jobTemplateId=Default%3A%3AJobTemplate%3A%3AMyTemplateFolder%2FMyTemplateName&jobId=140
Referrer: http://xxxx:8626/jobs/history
User: Admin
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0
Stack trace: at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Inedo.Otter.WebApplication.Pages.Jobs.CreateJobFromTemplatePage.VariablePrompts..ctor(IEnumerable`1 variables, Dictionary`2 selectedValues, VariableTemplateContext context)
at Inedo.Otter.WebApplication.Pages.Jobs.CreateJobFromTemplatePage.CreateChildControls()
at Inedo.Otter.WebApplication.Pages.OtterSimplePageBase.InitializeAsync()
at Inedo.Web.PageFree.SimplePageBase.ExecutePageLifeCycleAsync()
at Inedo.Web.PageFree.SimplePageBase.ProcessRequestAsync(AhHttpContext context)
at Inedo.Web.AhWebMiddleware.InvokeAsync(HttpContext context)
::HTTP Error on 19/12/2024 18:55:42::
I'm fairly certain it boils down to a simple null-ref check in the CreateJobFromTemplatePage
class (decompiled from Otter.WebApplication.dll
):
public VariablePrompts(IEnumerable<TemplateVariable> variables, Dictionary<string, string> selectedValues, VariableTemplateContext context)
{
object item;
CreateJobFromTemplatePage.VariablePrompts variablePrompt = this;
foreach (TemplateVariable variable in variables)
{
if (this.variableValues.ContainsKey(variable.Name))
{
continue;
}
TemplateVariable templateVariable = variable;
if (selectedValues != null)
{
item = selectedValues[variable.Name]; // <-- here
}
else
{
item = null;
}
if (item == null)
{
item = variable.InitialValue;
}
templateVariable.InitialValue = (string)item;
VariableTemplateInput variableTemplateInput = variable.Type.CreateInput(variable, context);
variablePrompt.get_Controls().Add(variableTemplateInput);
this.variableValues.Add(variable.Name, variableTemplateInput);
}
}
My guess is that you are not serializing unset/empty values or that they are not being deserialized correctly to the selectedValues
dictionary by the caller. Whether or not that is a larger problem is unknown, but you can probably bandage it here by simply changing to...
if (selectedValues != null || !selectedValues.ContainsKey(variable.Name))
{
item = selectedValues[variable.Name];
}
...without affecting the surrounding logic.