modelsbuilder / ModelsBuilder.Original

The Community Models Builder for Umbraco
MIT License
114 stars 49 forks source link

Invalid expression term on nullable property #186

Closed ghost closed 5 years ago

ghost commented 5 years ago

For a reason, I have some string properties on my document type, as these have a Label as their editor. The values of these properties are imported (and should not be editable in Umbraco). I'm using ModelsBuilder but when I define the following on my model, the ModelBuilder fails with the message below.

[IgnorePropertyType("purchasePrice")]
[IgnorePropertyType("resalePrice")]
public partial class ProductVariantContentModel
{
    [ImplementPropertyType("purchasePrice")]
    public decimal? PurchasePrice
    {
        get
        {
            if (this.HasValue("purchasePrice") == false)
                return null;

            var value = this.GetPropertyValue<string>("purchasePrice");
            if (decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal result))
                return result;

            return null;
        }
    }

    [ImplementPropertyType("resalePrice")]
    public decimal? ResalePrice
    {
        get
        {
            if (this.HasValue("resalePrice") == false)
                return null;

            var value = this.GetPropertyValue<string>("resalePrice");
            if (decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal result))
                return result;

            return null;
        }
    }
}

This results in the following message:

UmbracoModelsBuilder: UmbracoModelsBuilder failed to generate code: Exception: Response status code does not indicate success (InternalServerError)
{"Message":"An error has occurred.","ExceptionMessage":"Invalid expression term 'decimal'","ExceptionType":"Umbraco.ModelsBuilder.Building.CompilerException","StackTrace":"   at Umbraco.ModelsBuilder.Building.Compiler.ThrowExceptionFromDiagnostic(String path, String code, Diagnostic diagnostic) in D:\\d\\Zbu ModelsBuilder-7\\Umbraco.ModelsBuilder\\Building\\Compiler.cs:line 161\r\n   at Umbraco.ModelsBuilder.Building.Compiler.<>c__DisplayClass12_0.<GetCompilation>b__0(KeyValuePair`2 x) in D:\\d\\Zbu ModelsBuilder-7\\Umbraco.ModelsBuilder\\Building\\Compiler.cs:line 48\r\n   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()\r\n   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)\r\n   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)\r\n   at Umbraco.ModelsBuilder.Building.Compiler.GetCompilation(String assemblyName, IDictionary`2 files, SyntaxTree[]& trees) in D:\\d\\Zbu ModelsBuilder-7\\Umbraco.ModelsBuilder\\Building\\Compiler.cs:line 46\r\n   at Umbraco.ModelsBuilder.Building.CodeParser.Parse(IDictionary`2 files, IEnumerable`1 references) in D:\\d\\Zbu ModelsBuilder-7\\Umbraco.ModelsBuilder\\Building\\CodeParser.cs:line 38\r\n   at Umbraco.ModelsBuilder.Api.ApiHelper.GetModels(String modelsNamespace, IDictionary`2 files) in D:\\d\\Zbu ModelsBuilder-7\\Umbraco.ModelsBuilder\\Api\\ApiHelper.cs:line 16\r\n   at Umbraco.ModelsBuilder.Api.ModelsBuilderApiController.GetModels(GetModelsData data) in D:\\d\\Zbu ModelsBuilder-7\\Umbraco.ModelsBuilder.Api\\ModelsBuilderApiController.cs:line 65\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"}
UmbracoModelsBuilder:    at Umbraco.ModelsBuilder.Api.ApiClient.EnsureSuccess(HttpResponseMessage result)
   at Umbraco.ModelsBuilder.Api.ApiClient.GetModels(Dictionary`2 ourFiles, String modelsNamespace)
   at Umbraco.ModelsBuilder.CustomTool.CustomTool.UmbracoModelsBuilder.GenerateRaw(String wszInputFilePath, String wszDefaultNamespace, IntPtr[] rgbOutputFileContents, UInt32& pcbOutput, String& errMsg)

Commenting out the properties resolves the issue, and having them as nullable too. But that's not really an option...

zpqrtbnk commented 5 years ago

going to guess here... what happens if you replace the lines

if (decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal result))
  return result;

with

decimal result;
if (decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out result))
  return result;

?

The error we're seeing is, we fail to parse your code. And yet, your code is valid. But the syntax you used was introduced in C# version I-cannot-remember. In order for your syntax to be supported, you may want to experiment with the Umbraco.ModelsBuilder.LanguageVersion configuration setting (see Install And Configure) and use something like CSharp7.

Does this help?

ghost commented 5 years ago

Yup, that helps! I was under the impression that it was due to the nullable return type, but indeed it was the usage of the so-called Out variables introduced in C# 7.

We have ModelsBuilder 3.0.10 installed but changing the Umbraco.ModelsBuilder.LanguageVersion value to CSharp7 throws an "Invalid language version 'CSharp7'" ConfigurationErrorsException. In what version of ModelsBuilder is support for C# 7 introduced? Or am I missing another setting somewhere?

[ConfigurationErrorsException: Invalid language version &quot;CSharp7&quot;.]
   Umbraco.ModelsBuilder.Configuration.Config..ctor() in D:\d\Zbu ModelsBuilder-7\Umbraco.ModelsBuilder\Configuration\Config.cs:126
   Umbraco.ModelsBuilder.Configuration.&lt;&gt;c.&lt;ModelsBuilder&gt;b__1_0() in D:\d\Zbu ModelsBuilder-7\Umbraco.ModelsBuilder\Configuration\UmbracoConfigExtensions.cs:24
   System.Threading.LazyInitializer.EnsureInitializedCore(T&amp; target, Func`1 valueFactory) +21
   Umbraco.ModelsBuilder.Configuration.UmbracoConfigExtensions.ModelsBuilder(UmbracoConfig umbracoConfig) in D:\d\Zbu ModelsBuilder-7\Umbraco.ModelsBuilder\Configuration\UmbracoConfigExtensions.cs:25
   Umbraco.ModelsBuilder.Umbraco.LiveModelsProvider.get_IsEnabled() in D:\d\Zbu ModelsBuilder-7\Umbraco.ModelsBuilder\Umbraco\LiveModelsProvider.cs:26
   Umbraco.ModelsBuilder.Umbraco.LiveModelsProviderModule.Install() in D:\d\Zbu ModelsBuilder-7\Umbraco.ModelsBuilder\Umbraco\LiveModelsProvider.cs:132

[InvalidOperationException: The pre-application start initialization method Install on type Umbraco.ModelsBuilder.Umbraco.LiveModelsProviderModule threw an exception with the following error message: Invalid language version &quot;CSharp7&quot;..]
   System.Web.Compilation.BuildManager.InvokePreStartInitMethodsCore(ICollection`1 methods, Func`1 setHostingEnvironmentCultures) +850
   System.Web.Compilation.BuildManager.InvokePreStartInitMethods(ICollection`1 methods) +162
   System.Web.Compilation.BuildManager.CallPreStartInitMethods(String preStartInitListPath, Boolean&amp; isRefAssemblyLoaded) +128
   System.Web.Compilation.BuildManager.ExecutePreAppStart() +170
   System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException) +820

[HttpException (0x80004005): The pre-application start initialization method Install on type Umbraco.ModelsBuilder.Umbraco.LiveModelsProviderModule threw an exception with the following error message: Invalid language version &quot;CSharp7&quot;..]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +523
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +107
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +688
zpqrtbnk commented 5 years ago

Roslyn as shipped with ModelsBuilder for v7 stops at CSharp6 and does not support C# 7 indeed.

And... there is no plan to change this for v7.

ghost commented 5 years ago

Allright, then this issue can be closed ;-) And I think one should update the documentation on ModelsBuilder with this limitation.