Neon.Xunit.XunitExtensions.ErrorWriter.Error(string)

Here are the examples of the csharp api Neon.Xunit.XunitExtensions.ErrorWriter.Error(string) taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

1 Examples 7

19 Source : XunitExtensions.ValidateController.cs
with Apache License 2.0
from nforgeio

public static void ValidateController<TServiceController>(this IGeneratedServiceClient client)
        {
            // Verify that the schema for the generated code is compatable with this
            // version of the validator.  We currently require schema=1.

            var versionFields = client.GeneratorVersion.Split(':');

            if (versionFields.Length != 2 || versionFields[1] != "1")
            {
                throw new IncompatibleServiceException($"The generated service client code is not compatible with this version of the validator.  Consider upgrading to the latest Neon packages and rebuilding your service clients.");
            }

            // The idea here is to construct two dictionaries that map method signatures
            // [MethodInfo] instances.  One dictionary will do this for [TServiceImplementation]
            // and the other one for the [client] preplaceded.
            //
            // The method signature will be formatted like:
            //
            //      HTTPMethod["RouteTemplate"]: ReturnType (Param0Type, Param1Type,...)
            //
            // Note that we're only going to include parameters from the client that
            // are tagged by [GeneratedParam].  The remaining parameters are client
            // specific, like timeout or CancellationToken.
            //
            // We're also going to use the request route template (in brackets) rather 
            // than the method name (because the names may differ).
            //
            // We'll use these dictionaries to ensure that both the service controller
            // and the generated service client implement the same methods and then
            // we'll go back and verify the details for each matching method.
            //
            // NOTE: By default, we replacedume that all public non-static service controller
            // methods will be validated against the generated service client.  In rare
            // situations, it may be useful to have service controller endpoint that are
            // not covered by the generated clients.  In these situations, you may
            // tag these methods with [Neon.Common.ModelGen.NoValidation] and the those
            // methods will be ignored.

            var controllerMethods = new Dictionary<string, MethodInfo>();
            var clientMethods     = new Dictionary<string, MethodInfo>();
            var controllerType    = typeof(TServiceController);
            var clientType        = client.GetType();
            var errors            = new ErrorWriter();

            // Ensure that the service controller and client route templates match.

            var generatedClientAttribute = clientType.GetCustomAttribute<GeneratedClientAttribute>();
            var controllerRouteAttribute = controllerType.GetCustomAttribute<Microsoft.AspNetCore.Mvc.RouteAttribute>();

            if (generatedClientAttribute == null)
            {
                errors.Error($"[{clientType.Name}] must be tagged with a [GeneratedClient] attribute.");
            }

            if (controllerRouteAttribute == null)
            {
                errors.Error($"[{controllerType.Name}] must be tagged with a [Route] attribute.");
            }

            if (generatedClientAttribute != null && controllerRouteAttribute != null)
            {
                if (generatedClientAttribute.RouteTemplate != controllerRouteAttribute.Template)
                {
                    errors.Error($"[{controllerType.Name}] has [Route(\"{controllerRouteAttribute.Template}\")] which does not match [{clientType.Name}] client's [Route(\"{generatedClientAttribute.RouteTemplate}\")].");
                }
            }

            // Load the controller methods.

            foreach (var method in controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
            {
                var noValidationAttribute = method.GetCustomAttribute<NoControllerValidationAttribute>();

                if (noValidationAttribute != null)
                {
                    continue;
                }

                if (method.IsSpecialName)
                {
                    // Ignore property setters, getters, etc.

                    continue;
                }

                if (method.DeclaringType != controllerType && method.GetCustomAttribute<ControllerValidationAttribute>() == null)
                {
                    // Any service controller methods that are not implemented directly in the 
                    // controller clreplaced or are not tagged by [ControllerValidation] are not
                    // considered for validation.  This filters out base object methods
                    // like ToString(), GetType(),...

                    continue;
                }

                if (method.ReturnType == typeof(Microsoft.AspNetCore.Mvc.IActionResult))
                {
                    errors.Error($"Controller method [{method.Name}(...)] returns [IActionResult] which is not supported.  Use [ActionResult] or [ActionResult<T>] instead.");
                }

                var     routeAttribute = method.GetCustomAttribute<Microsoft.AspNetCore.Mvc.RouteAttribute>();
                string  routeTemplate;

                if (routeAttribute != null)
                {
                    routeTemplate = routeAttribute.Template;
                }
                else
                {
                    routeTemplate = method.Name;
                }

                var httpMethod = "GET";
                var methodName = method.Name.ToUpperInvariant();

                if (method.GetCustomAttribute<Microsoft.AspNetCore.Mvc.HttpDeleteAttribute>() != null)
                {
                    httpMethod = "DELETE";
                }
                else if (method.GetCustomAttribute<Microsoft.AspNetCore.Mvc.HttpGetAttribute>() != null)
                {
                    httpMethod = "GET";
                }
                else if (method.GetCustomAttribute<Microsoft.AspNetCore.Mvc.HttpHeadAttribute>() != null)
                {
                    httpMethod = "HEAD";
                }
                else if (method.GetCustomAttribute<Microsoft.AspNetCore.Mvc.HttpOptionsAttribute>() != null)
                {
                    httpMethod = "OPTIONS";
                }
                else if (method.GetCustomAttribute<Microsoft.AspNetCore.Mvc.HttpPatchAttribute>() != null)
                {
                    httpMethod = "PATCH";
                }
                else if (method.GetCustomAttribute<Microsoft.AspNetCore.Mvc.HttpPostAttribute>() != null)
                {
                    httpMethod = "POST";
                }
                else if (method.GetCustomAttribute<Microsoft.AspNetCore.Mvc.HttpPutAttribute>() != null)
                {
                    httpMethod = "PUT";
                }
                else if (methodName.StartsWith("DELETE"))
                {
                    httpMethod = "DELETE";
                }
                else if (methodName.StartsWith("GET"))
                {
                    httpMethod = "GET";
                }
                else if (methodName.StartsWith("HEAD"))
                {
                    httpMethod = "HEAD";
                }
                else if (methodName.StartsWith("OPTIONS"))
                {
                    httpMethod = "OPTIONS";
                }
                else if (methodName.StartsWith("PATCH"))
                {
                    httpMethod = "PATCH";
                }
                else if (methodName.StartsWith("POST"))
                {
                    httpMethod = "POST";
                }
                else if (methodName.StartsWith("PUT"))
                {
                    httpMethod = "PUT";
                }

                var signature = GetMethodSignature(method, httpMethod, routeTemplate, requireGeneratedParamAttribute: false);

                if (controllerMethods.TryGetValue(signature, out var existing))
                {
                    errors.Error($"[{controllerType.Name}] has multiple methods including\r\n\r\n    {method.Name}(...)] and\r\n\r\n    [{existing.Name}(...)]\r\n\r\n    with the same parameters at endpoint [{httpMethod}:{routeTemplate}].");
                }
                else
                {
                    controllerMethods.Add(signature, method);
                }
            }

            // Load the client methods that call service endpoints.

            foreach (var method in clientType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
            {
                var generatedMethodAttribute = method.GetCustomAttribute<GeneratedMethodAttribute>();

                if (generatedMethodAttribute == null)
                {
                    continue;
                }

                var signature = GetMethodSignature(method, generatedMethodAttribute.HttpMethod, generatedMethodAttribute.RouteTemplate, requireGeneratedParamAttribute: true);

                if (clientMethods.TryGetValue(signature, out var existing))
                {
                    errors.Error($"[{clientType.Name}] has multiple methods including\r\n\r\n    [{method.Name}(...)] and\r\n\t\n    [{existing.Name}(...)]\r\n\r\n    with the same parameters at endpoint [{generatedMethodAttribute.HttpMethod}:{generatedMethodAttribute.RouteTemplate}].");
                }
                else
                {
                    clientMethods.Add(signature, method);
                }
            }

            // Ensure that all of the client methods are also present in the controller.

            foreach (var clientMethod in clientMethods)
            {
                if (!controllerMethods.ContainsKey(clientMethod.Key))
                {
                    errors.Error($"Service controller [{controllerType.Name}] lacks a method that corresponds to:\r\n\r\n    {clientType.Name}::{clientMethod.Value}\r\n\r\n    with signature:\r\n\r\n    {clientMethod.Key}]");
                }
            }

            // Ensure that all of the controller methods are also present in the client.

            foreach (var controllerMethod in controllerMethods)
            {
                if (!clientMethods.ContainsKey(controllerMethod.Key))
                {
                    errors.Error($"Service client [{clientType.Name}] lacks a method that corresponds to:\r\n\r\n    {controllerType.Name}::{controllerMethod.Value}\r\n\r\n    with signature:\r\n\r\n    {controllerMethod.Key}");
                }
            }

            // Do a detailed comparision of the method return types and parameters.

            foreach (var clientMethod in clientMethods)
            {
                if (controllerMethods.TryGetValue(clientMethod.Key, out var controllerMethod))
                {
                    var clientParams     = clientMethod.Value.GetParameters();
                    var controllerParams = controllerMethod.GetParameters();

                    // Note that we're using the controller parameter count rather than
                    // the client parameter count because the client methods were generated
                    // with extra (optional) parameters to specify timeout, retry policy, etc.

                    for (int i = 0; i < controllerParams.Length; i++)
                    {
                        var clientParam          = clientParams[i];
                        var controllerParam      = controllerParams[i];
                        var generatedClientParam = clientParam.GetCustomAttribute<GeneratedParamAttribute>();

                        if (generatedClientParam == null)
                        {
                            // Only the leading client method parameters that are actually preplaceded to the
                            // service have this attribute, so we can ignore parameters after these.

                            break;
                        }

                        // Ensure that parameter optionality is consistent.

                        if (clientParam.IsOptional != controllerParam.IsOptional)
                        {
                            if (controllerParam.IsOptional && !clientParam.IsOptional)
                            {
                                errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is optional which conflicts with the service definition which is not optional.");
                            }
                            else
                            {
                                errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is not optional which conflicts with the service definition which is optional.");
                            }
                        }

                        if (clientParam.IsOptional)
                        {
                            var defaultsAreEqual = true;

                            if ((clientParam.DefaultValue == null) != (controllerParam.DefaultValue == null))
                            {
                                defaultsAreEqual = false;
                            }
                            else if (clientParam.DefaultValue != null)
                            {
                                defaultsAreEqual = clientParam.DefaultValue.Equals(controllerParam.DefaultValue);
                            }

                            if (!defaultsAreEqual)
                            {
                                errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] default value [{clientParam.DefaultValue}] does not match the controller default value [{controllerParam.DefaultValue}].");
                            }
                        }

                        // Ensure that the method for transmitting the parameter is consistent.

                        var fromQueryAttribute = controllerParam.GetCustomAttribute<Microsoft.AspNetCore.Mvc.FromQueryAttribute>();

                        if (fromQueryAttribute != null)
                        {
                            if (string.IsNullOrEmpty(fromQueryAttribute.Name))
                            {
                                fromQueryAttribute.Name = controllerParam.Name;
                            }

                            if (generatedClientParam.PreplacedAs != PreplacedAs.Query)
                            {
                                errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is preplaceded as [From{generatedClientParam.PreplacedAs}] which doesn't match the controller method parameter which requires [FromQuery].");
                            }
                            else if (generatedClientParam.Name != fromQueryAttribute.Name)
                            {
                                errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is preplaceded using name [{generatedClientParam.Name}] which doesn't match the controller method parameter which requires [{fromQueryAttribute.Name}].");
                            }
                        }
                        else
                        {
                            var fromRouteAttribute = controllerParam.GetCustomAttribute<Microsoft.AspNetCore.Mvc.FromRouteAttribute>();

                            if (fromRouteAttribute != null)
                            {
                                if (generatedClientParam.PreplacedAs != PreplacedAs.Route)
                                {
                                    errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is preplaceded as [From{generatedClientParam.PreplacedAs}] which doesn't match the controller method parameter which requires [FromRoute].");
                                }
                                else if (generatedClientParam.Name != fromRouteAttribute.Name)
                                {
                                    errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is preplaceded using route name [{generatedClientParam.Name}] which doesn't match the controller method parameter which requires [{fromRouteAttribute.Name}].");
                                }
                            }
                            else
                            {
                                var fromHeaderAttribute = controllerParam.GetCustomAttribute<Microsoft.AspNetCore.Mvc.FromHeaderAttribute>();

                                if (fromHeaderAttribute != null)
                                {
                                    if (generatedClientParam.PreplacedAs != PreplacedAs.Header)
                                    {
                                        errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is preplaceded as [From{generatedClientParam.PreplacedAs}] which doesn't match the controller method parameter which requires [FromHeader].");
                                    }
                                    else if (generatedClientParam.Name != fromHeaderAttribute.Name)
                                    {
                                        errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is preplaceded using HTTP header [{generatedClientParam.Name}] which doesn't match the controller method parameter which requires [{fromHeaderAttribute.Name}].");
                                    }
                                }
                                else
                                {
                                    var fromBodyAttribute = controllerParam.GetCustomAttribute<Microsoft.AspNetCore.Mvc.FromBodyAttribute>();

                                    if (fromBodyAttribute != null)
                                    {
                                        if (generatedClientParam.PreplacedAs != PreplacedAs.Body)
                                        {
                                            errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is preplaceded as [From{generatedClientParam.PreplacedAs}] which doesn't match the controller method parameter which requires [FromBody].");
                                        }
                                    }
                                    else
                                    {
                                        // We default to [FromQuery] when nothing else is specified.

                                        if (generatedClientParam.PreplacedAs != PreplacedAs.Query)
                                        {
                                            errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is preplaceded as [From{generatedClientParam.PreplacedAs}] which doesn't match the controller method parameter which implicitly specifies [FromQuery].");
                                        }
                                        else if (generatedClientParam.Name != controllerParam.Name)
                                        {
                                            errors.Error($"[{clientType.Name}::{clientMethod}(...)] parameter [{clientParam.Name}] is preplaceded using HTTP query parameter [{generatedClientParam.Name}] which doesn't match the controller method parameter which requires [{controllerParam.Name}].");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (errors.HasErrors)
            {
                throw new IncompatibleServiceException("\r\n\r\n" + errors.ToString());
            }
        }