Пример #1
0
        private string GenerateDtoPropagatePropertyAccessPath(ApiDto apiDto, List <ApiDtoField> apiDtoFields)
        {
            var indent  = new Indent();
            var builder = new StringBuilder();

            var modifier = apiDto.Extends != null
                ? "override"
                : apiDto.HierarchyRole != HierarchyRole.FINAL
                    ? "virtual"
                    : string.Empty;

            builder.AppendLine($"{indent}public {modifier} void {nameof(IPropagatePropertyAccessPath.SetAccessPath)}(string path, bool validateHasBeenSet)");
            builder.AppendLine($"{indent}{{");
            indent.Increment();

            foreach (var apiDtoField in apiDtoFields)
            {
                var backingFieldNameForField = apiDtoField.Field.ToCSharpBackingFieldName();

                builder.AppendLine($"{indent}{backingFieldNameForField}.{nameof(IPropagatePropertyAccessPath.SetAccessPath)}(path, validateHasBeenSet);");
            }

            indent.Decrement();
            builder.AppendLine($"{indent}}}");

            return(builder.ToString());
        }
Пример #2
0
        private List <ApiDtoField> DetermineFieldsToGenerateFor(ApiDto apiDto)
        {
            var dtoHierarchyFieldNames = new List <string>();

            if (apiDto.Extends != null && _codeGenerationContext.TryGetDto(apiDto.Extends.Id, out var apiDtoExtends))
            {
                dtoHierarchyFieldNames.AddRange(apiDtoExtends !.Fields.Select(it => it.Field.Name));
            }

            // For implements, add all referenced types' fields
            var apiDtoFields = new List <ApiDtoField>();

            if (apiDto.Implements != null)
            {
                foreach (var dtoReference in apiDto.Implements)
                {
                    if (_codeGenerationContext.TryGetDto(dtoReference.Id, out var apiDtoImplements))
                    {
                        apiDtoFields.AddRange(apiDtoImplements !.Fields);
                    }
                }
            }

            // Add own fields
            apiDtoFields.AddRange(apiDto.Fields);

            // Filter out properties that are already present in parent types
            apiDtoFields = apiDtoFields
                           .Where(it => !dtoHierarchyFieldNames.Contains(it.Field.Name))
                           .ToList();

            return(apiDtoFields);
        }
Пример #3
0
        public async Task <PersonalDataResponse> GetPersonalDataAsync(ApiDto apiDto, Dto.CompanyDto company, List <MailBodyDto> mailBodyList)
        {
            var                httpClient = HttpClientHelper.Get(apiDto);
            string             body       = "";
            string             uriString  = company.PersonalDataUrl + $"?REQUESTOR={HttpUtility.UrlEncode(company.Requestor)}&PASSWORD={HttpUtility.UrlEncode(company.Password)}&COMPANY={HttpUtility.UrlEncode(company.ExternalCode)}";
            HttpRequestMessage request    = new HttpRequestMessage
            {
                Method     = new HttpMethod("POST"),
                RequestUri = new Uri(uriString),
                Content    = new StringContent(body)
            };

            httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {company.AccessToken}");
            httpClient.DefaultRequestHeaders.Add("apikey", company.ApiKey);
            httpClient.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
            var response = await httpClient.SendAsync(request);

            if (response.IsSuccessStatusCode)
            {
                return(await response.Content.ReadAsJsonAsync <PersonalDataResponse>());
            }
            var message = await response.Content.ReadAsStringAsync();

            mailBodyList.Add(new MailBodyDto {
                CompanyCode = company.Code, Message = message
            });
            return(null);
        }
Пример #4
0
        public static async Task UpdateAsync(ApiDto apiDto, MailDto mailDto, ContextDto contextDto)
        {
            try
            {
                var httpClient    = HttpClientHelper.Get(apiDto);
                var integratorDto = await GetIntegratorAsync(httpClient, MyStatusId);

                if (integratorDto != null && integratorDto.Version == MyVersion)
                {
                    return;
                }
                await ExternalTableHelper.PostAsync(httpClient, "HrLinkCompany", GetExternalTablePostModel());

                await DatabaseHelper.RecreateViewsAsync(httpClient, GetSkillsWorkflowIntegrationHrLinkCompanies());

                if (!await DatabaseHelper.ExistsViewAsync(apiDto, "SkillsWorkflowIntegrationHrLinkCompanies"))
                {
                    throw new Exception("View SkillsWorkflowIntegrationHrLinkCompanies not created.");
                }
                await PostIntegratorAsync(httpClient);
            }
            catch (Exception exception)
            {
                var groupId = contextDto.TenantId.ToString() + "-" + Updater.MyStatusId.ToString();
                await MailHelper.SendEmailAsync(mailDto, "Error updating HrLink structure.", MailHelper.GetBodyTextOf(contextDto, exception.InnerException?.Message ?? exception.Message), mailDto.AdministratorMail, null, true, groupId);
            }
        }
Пример #5
0
        public async Task TestGetDto()
        {
            ApiResponse data = await _Client.GetMyDto();

            ApiDto dto = data.GetTypedContent <ApiDto>();

            Assert.IsNotNull(dto);
        }
Пример #6
0
        public static string ToCSharpFactoryMethodName(this ApiDto subject, ApiDto parent)
        {
            var classNameForParent  = CSharpIdentifier.ForClassOrNamespace(parent.Name);
            var classNameForSubject = CSharpIdentifier.ForClassOrNamespace(subject.Name);
            var factoryMethodName   = CSharpIdentifier.ForClassOrNamespace(
                classNameForSubject.Replace(classNameForParent, string.Empty));

            return(factoryMethodName);
        }
Пример #7
0
        public async Task <bool> ImportAsync(ApiDto apiDto, Dto.CompanyDto company, PersonalDataResponse personalData, JobDataResponse jobData, List <MailBodyDto> mailBodyList)
        {
            var persons    = personalData == null ? new List <Person>() : personalData.SoapenvEnvelope.Body.ApiVersionPersons.Persons.ToList();
            var jobs       = jobData == null ? new List <JobDataWithComp>() : jobData.SoapenvEnvelope.Body.ApiVersionJobs.JobDataWithCompList.ToList();
            int count      = 1;
            var httpClient = HttpClientHelper.Get(apiDto);
            var imported   = true;

            foreach (var person in persons)
            {
                var progressMessage = $"Importing {count++} of {persons.Count}.";
                var externalId      = person.Emplid.Text;
                var userName        = person.SubNames.NameDisplay.Text;
                var job             = jobs.FirstOrDefault(j => j.Job.Emplid.Text == externalId);
                if (job == null)
                {
                    await LogHelper.SaveLogAsync(apiDto, company.Code, company.CompanyId, Updater.MyStatusId, "User", userName, $"-- Not Imported - Job data must exists for employeeid {externalId} --", progressMessage, JsonConvert.SerializeObject(person));

                    imported = false;
                    continue;
                }
                var department = await GetDepartmentAsync(httpClient, company.CompanyId, job.Department.Deptid.Text);

                if (department == null)
                {
                    await ApiHelper.SaveLogAsync(apiDto, company.Code, company.CompanyId, Updater.MyStatusId, "User", userName, $"Department does not exists for external id {job.Department.Deptid.Text}.", progressMessage, JsonConvert.SerializeObject(person));

                    continue;
                }
                var isActive    = job.Job.EmplStatus.Text == "A";
                var employeeDto = await SaveEmployeeAsync(httpClient, company, externalId, userName, isActive, progressMessage, mailBodyList);

                if (employeeDto == null)
                {
                    imported = false;
                    continue;
                }
                var savedUserTypology = await SaveUserTypologyAsync(httpClient, company, department.Id, job, progressMessage);

                if (!savedUserTypology)
                {
                    imported = false;
                    continue;
                }
                var savedUserDto = await SaveUserAsync(httpClient, company, externalId, userName, isActive, person, job, employeeDto.Id, progressMessage, mailBodyList);

                if (savedUserDto == null)
                {
                    imported = false;
                    continue;
                }
            }
            return(imported);
        }
Пример #8
0
        public IHttpActionResult GetDto()
        {
            ApiDto dto = new ApiDto()
            {
                Id       = 12,
                Name     = "ApiDto",
                ParentId = 22
            };

            return(Ok(dto));
        }
        //跳转青书对应角色账号
        public ActionResult GoToQinshu()
        {
            var qinshukey = ConfigurationManager.AppSettings["QinshuKey"];

            if (string.IsNullOrWhiteSpace(qinshukey))
            {
                return(Content("此学校未配置青书对应学校编号"));
            }

            string url = "http://www.qingshuxuetang.com/QingShuHomeSvc/v1/auth/login";

            if (!IsLogin())
            {
                return(Redirect("/AdminBase/Index"));
            }

            using (var ad = new IYunEntities())
            {
                var admin = ad.YD_Sts_StuInfo.First(u => u.id == LoginId);

                if (string.IsNullOrWhiteSpace(admin.y_loginName))
                {
                    return(Content("此账号未配置青书对应账号"));
                }

                var dto = new ApiDto()
                {
                    collegeSymbol = qinshukey,
                    name          = admin.y_loginName,
                    password      = admin.y_password
                };

                var req = JsonConvert.SerializeObject(dto);

                string str = Post_Request_API(req, url);

                var result = JsonConvert.DeserializeObject <ApiResultDto>(str);

                if (result.hr == 0 && result.data != null)
                {
                    return(Redirect(result.data.url));
                }
                return(Content(result.message));
            }
        }
Пример #10
0
        public IHttpActionResult GetDtos()
        {
            ApiDto dto1 = new ApiDto()
            {
                Id       = 12,
                Name     = "ApiDto1",
                ParentId = 13
            };
            ApiDto dto2 = new ApiDto()
            {
                Id       = 13,
                Name     = "ApiDto2",
                ParentId = 22
            };

            return(Ok(new List <ApiDto>()
            {
                dto1, dto2
            }));
        }
        public string GeneratePartialClassFor(ApiDto apiDto)
        {
            var indent  = new Indent();
            var builder = new StringBuilder();

            var typeNameForDto        = apiDto.ToCSharpClassName();
            var typeNameForPartialDto = $"Partial<{typeNameForDto}>";

            builder.AppendLine($"{indent}public static class {typeNameForDto}PartialExtensions");
            builder.AppendLine($"{indent}{{");
            indent.Increment();

            foreach (var apiDtoField in apiDto.Fields)
            {
                builder.Append(indent.Wrap(GenerateExtensionMethodsFor(typeNameForDto, typeNameForPartialDto, apiDtoField.Field)));
            }

            indent.Decrement();
            builder.AppendLine($"{indent}}}");
            return(builder.ToString());
        }
        private static void AddRequestBodyTypesToDtos(CodeGenerationContext context, IEnumerable <ApiResource> resources, string parentResourcePath)
        {
            foreach (var apiResource in resources)
            {
                var resourcePath = (parentResourcePath.Length > 0
                    ? parentResourcePath + "/" + apiResource.Path.Segments.ToPath()
                    : apiResource.Path.Segments.ToPath()).TrimEnd('/');

                foreach (var apiEndpoint in apiResource.Endpoints)
                {
                    if (apiEndpoint.RequestBody != null && apiEndpoint.RequestBody.Kind == ApiFieldType.Object.ObjectKind.REQUEST_BODY)
                    {
                        // Endpoint path
                        var endpointPath = (resourcePath + "/" + apiEndpoint.Path.Segments.ToPath()).TrimEnd('/');

                        // Expected class name
                        var typeNameForRequestBody = apiEndpoint.ToCSharpRequestBodyClassName(endpointPath) !;
                        var classIdForRequestBody  = typeNameForRequestBody.ToLowerInvariant();

                        // See if we have seen the anonymous class before (and if not, add it)
                        if (!context.TryGetDto(classIdForRequestBody, out var requestBodyClass))
                        {
                            requestBodyClass = new ApiDto
                            {
                                Id     = classIdForRequestBody,
                                Name   = typeNameForRequestBody,
                                Fields = apiEndpoint.RequestBody.Fields.Select(it => new ApiDtoField {
                                    Field = it
                                }).ToList()
                            };

                            context.AddDto(classIdForRequestBody, requestBodyClass);
                        }
                    }
                }

                AddRequestBodyTypesToDtos(context, apiResource.NestedResources, resourcePath);
            }
        }
Пример #13
0
        private async Task <List <TenantCompaniesDto> > GetTenantCompanies()
        {
            var tenantCompanies = new List <TenantCompaniesDto>();

            foreach (var tenant in Tenants)
            {
                var apiDto = new ApiDto {
                    Url = tenant.Url, Id = tenant.Id, Secret = tenant.Secret
                };
                var companies = await _companyHelper.GetAsync(apiDto);

                if (companies == null || companies.Count == 0)
                {
                    continue;
                }
                var tenantCompaniesDto = new TenantCompaniesDto {
                    Api = apiDto, Companies = companies
                };
                tenantCompanies.Add(tenantCompaniesDto);
            }
            return(tenantCompanies);
        }
Пример #14
0
        public async Task <List <CompanyDto> > GetAsync(ApiDto apiDto)
        {
            var httpClient     = HttpClientHelper.Get(apiDto);
            var policeResponse = await PollyHelper.GetHttpResponseMessage(httpClient, ConfigurationManager.AppSettings["RetryPolicy:Http:RetryTimeoutMinutes"], "/api/skillviews/search?viewName=SkillsWorkflowIntegrationHrLinkCompanies");

            if (!policeResponse.IsSuccessStatusCode)
            {
                throw new Exception("Error searching view named SkillsWorkflowIntegrationHrLinkCompanies. " + Environment.NewLine + policeResponse.Content.ReadAsStringAsync().Result);
            }
            var searchedViews = await policeResponse.Content.ReadAsJsonAsync <List <string> >();

            if (searchedViews.Count == 0)
            {
                return(new List <CompanyDto>());
            }
            policeResponse = await PollyHelper.GetHttpResponseMessage(httpClient, ConfigurationManager.AppSettings["RetryPolicy:Http:RetryTimeoutMinutes"], "/api/skillviews/SkillsWorkflowIntegrationHrLinkCompanies");

            if (!policeResponse.IsSuccessStatusCode)
            {
                throw new Exception("Error executing view named SkillsWorkflowIntegrationHrLinkCompanies. " + Environment.NewLine + policeResponse.Content.ReadAsStringAsync().Result);
            }
            return(await policeResponse.Content.ReadAsJsonAsync <List <CompanyDto> >());
        }
Пример #15
0
 public void AddDto(string id, ApiDto apiDto) => _idToDtoMap[id] = apiDto;
Пример #16
0
        static async Task Main(string[] args)
        {
            Console.WriteLine("<Program> Starting");
            var           tenantsSection = Helpers.TenantSectionHelper.Get();
            List <ApiDto> tenants        = new List <ApiDto>();

            foreach (var tenantSection in tenantsSection)
            {
                tenants.Add(new ApiDto {
                    Url = tenantSection.ApiUrl, Id = tenantSection.ApiId, Secret = tenantSection.ApiSecret
                });
            }
            var mailDto = MailHelper.ReadConfigurationSettings();

            if (args.Length == 4 && args[0] == "-update")
            {
                var apiDto = new ApiDto {
                    Url = args[1], Id = args[2], Secret = args[3]
                };
                var contextDto = await ApiHelper.GetContextDtoAsync(apiDto);

                await Updater.UpdateAsync(apiDto, mailDto, contextDto);

                return;
            }
            if (args.Length == 1 && args[0] == "-status")
            {
                foreach (var tenant in tenants)
                {
                    Console.WriteLine(Tester.Execute(tenant.Url, tenant.Id, tenant.Secret));
                }
                return;
            }
            if (args.Length == 1 && args[0] == "-update")
            {
                foreach (var tenant in tenants)
                {
                    var contextDto = await ApiHelper.GetContextDtoAsync(tenant);

                    await Updater.UpdateAsync(tenant, mailDto, contextDto);
                }
                return;
            }
            if (args.Length == 0)
            {
                var controller = new Controller(tenants, mailDto);
                await controller.ExecuteAsync();

                return;
            }
            if (args.Length == 2 && args[0] == "-status")
            {
                foreach (var tenant in tenants)
                {
                    Guid id;
                    if (!Guid.TryParse(args[1], out id))
                    {
                        return;
                    }
                    var result = Tester.Execute(tenant.Url, tenant.Id, tenant.Secret);
                    PortalHelper.Start(id, result).Wait();
                }
            }
            Console.Write("<Program> Ending");
        }
Пример #17
0
 public static string ToCSharpClassName(this ApiDto subject)
 => CSharpIdentifier.ForClassOrNamespace(subject.Name);
Пример #18
0
        public async Task <bool> ImportAsync(ApiDto api, Dto.CompanyDto company, PersonalDataResponse personalData, JobDataResponse jobData, List <MailBodyDto> mailBodyList)
        {
            var persons    = personalData == null ? new List <Person>() : personalData.SoapenvEnvelope.Body.ApiVersionPersons.Persons.ToList();
            var jobs       = jobData == null ? new List <JobDataWithComp>() : jobData.SoapenvEnvelope.Body.ApiVersionJobs.JobDataWithCompList.ToList();
            int count      = 1;
            var httpClient = HttpClientHelper.Get(api);
            var imported   = true;

            foreach (var person in persons)
            {
                var progressMessage = $"Importing {count++} of {persons.Count}.";
                var userId          = Guid.Empty;
                var externalId      = person.Emplid.Text.ToString();
                var userName        = person.SubNames.NameDisplay.Text;
                var job             = jobs.FirstOrDefault(j => j.Job.Emplid.Text.ToString(CultureInfo.InvariantCulture) == externalId);
                if (job == null)
                {
                    await LogHelper.SaveLogAsync(httpClient, company.Code, company.CompanyId, Updater.MyStatusId, "User", userName, $"-- Not Imported - Job data must exists for employeeid {externalId} --", progressMessage, JsonConvert.SerializeObject(person));

                    imported = false;
                    continue;
                }
                var department = await GetDepartmentAsync(httpClient, company.CompanyId, job.Department.Deptid.Text);

                if (department == null)
                {
                    await ApiHelper.SaveLogAsync(httpClient, company.Code, company.CompanyId, Updater.MyStatusId, "User", userName, $"Department does not exists for external id {job.Department.Deptid.Text}.", progressMessage, JsonConvert.SerializeObject(person));

                    continue;
                }
                var isActive = job.Job.EmplStatus.Text == "A";
                var documentUserFieldValueDtos = await GetUserIdByHrLinkIdAsync(httpClient, person.Emplid.Text.ToString());

                if (documentUserFieldValueDtos.Count > 1)
                {
                    await ApiHelper.SaveLogAsync(httpClient, company.Code, company.CompanyId, Updater.MyStatusId, "User", userName, $"Exists several users with {person.Emplid.Text} HRLinkID.", progressMessage, JsonConvert.SerializeObject(person));

                    return(false);
                }
                if (documentUserFieldValueDtos.Count == 1)
                {
                    var user = await GetUserAsync(httpClient, documentUserFieldValueDtos[0].DocumentId);

                    externalId = user.ExternalId;
                    userId     = user.Id;
                }
                else
                {
                    externalId = (externalId.Length == 10 && externalId.Substring(2, 2) == "00") ? externalId.Remove(2, 2) : externalId;
                }
                var employeeDto = await SaveEmployeeAsync(httpClient, company, externalId, userName, isActive, progressMessage, mailBodyList);

                if (employeeDto == null)
                {
                    imported = false;
                    continue;
                }
                var savedUserTypology = await SaveUserTypologyAsync(httpClient, company, department.Id, job, progressMessage);

                if (!savedUserTypology)
                {
                    imported = false;
                    continue;
                }
                var savedUserDto = await SaveUserAsync(httpClient, company, userId, externalId, userName, isActive, person, job, employeeDto.Id, progressMessage, mailBodyList);

                if (savedUserDto == null)
                {
                    imported = false;
                    continue;
                }
                var documentUserFieldValueBatchPutModel = new DocumentUserFieldValueBatchPutModel
                {
                    DocumentId              = savedUserDto.Id,
                    DocumentTypeName        = "User",
                    DocumentUserFieldValues = new List <DocumentUserFieldValue>()
                };
                documentUserFieldValueBatchPutModel.DocumentUserFieldValues.Add(new DocumentUserFieldValue {
                    ColumnName = "HRLinkId", Value = person.Emplid.Text.ToString(), ColumnDataTypeId = (int)ColumnDataType.Varchar50
                });
                await SaveDocumentUserFieldValueAsync(httpClient, company, documentUserFieldValueBatchPutModel, progressMessage);
            }
            return(imported);
        }
Пример #19
0
        public string GenerateDtoDefinition(ApiDto apiDto)
        {
            var indent  = new Indent();
            var builder = new StringBuilder();

            var typeNameForDto = apiDto.ToCSharpClassName();

            if (apiDto.Deprecation != null)
            {
                builder.AppendLine(apiDto.Deprecation.ToCSharpDeprecation());
            }

            if (apiDto.HierarchyRole != HierarchyRole.INTERFACE && apiDto.Extends == null && apiDto.Inheritors.Count > 0)
            {
                // When extending another DTO, make sure to apply a converter
                builder.AppendLine($"{indent}[JsonConverter(typeof(ClassNameDtoTypeConverter))]");
            }

            var modifierForDto = apiDto.HierarchyRole == HierarchyRole.INTERFACE
                ? "interface"
                : apiDto.HierarchyRole == HierarchyRole.ABSTRACT
                    ? "abstract class"
                    : apiDto.HierarchyRole == HierarchyRole.FINAL
                        ? "sealed class"
                        : "class";

            var dtoHierarchy           = new List <string>();
            var dtoHierarchyFieldNames = new List <string>();

            if (apiDto.Extends != null && _codeGenerationContext.TryGetDto(apiDto.Extends.Id, out var apiDtoExtends))
            {
                dtoHierarchy.Add(apiDtoExtends !.ToCSharpClassName());
                dtoHierarchyFieldNames.AddRange(apiDtoExtends !.Fields.Select(it => it.Field.Name));
            }
            if (apiDto.Implements != null)
            {
                foreach (var dtoImplements in apiDto.Implements)
                {
                    if (_codeGenerationContext.TryGetDto(dtoImplements.Id, out var apiDtoImplements))
                    {
                        dtoHierarchy.Add(apiDtoImplements !.ToCSharpClassName());
                    }
                }
            }
            if (dtoHierarchy.Count > 0 || apiDto.Inheritors.Count > 0)
            {
                dtoHierarchy.Add(nameof(IClassNameConvertible));
            }

            dtoHierarchy.Add(nameof(IPropagatePropertyAccessPath));

            builder.AppendLine($"{indent}public {modifierForDto} {typeNameForDto}");
            indent.Increment();
            builder.AppendLine($"{indent} : " + string.Join(", ", dtoHierarchy));
            indent.Decrement();

            builder.AppendLine($"{indent}{{");
            indent.Increment();

            // When in a hierarchy with IClassNameConvertible, make sure we can capture the class name.
            if (dtoHierarchy.Contains(nameof(IClassNameConvertible)) && apiDto.HierarchyRole != HierarchyRole.INTERFACE)
            {
                var modifierForClassNameProperty = apiDto.Extends == null
                    ? apiDto.HierarchyRole != HierarchyRole.FINAL
                        ? "virtual" // Parent
                        : ""
                    : "override";   // Inheritor

                builder.AppendLine($"{indent}[JsonPropertyName(\"className\")]");
                builder.AppendLine($"{indent}public {modifierForClassNameProperty} string? ClassName => \"{apiDto.Name}\";");
                builder.AppendLine($"{indent}");
            }

            // Determine list of fields
            var apiDtoFields = DetermineFieldsToGenerateFor(apiDto);

            // Generate factories for inheritors
            foreach (var apiDtoInheritorReference in apiDto.Inheritors)
            {
                if (_codeGenerationContext.TryGetDto(apiDtoInheritorReference.Id, out var apiDtoInheritor) &&
                    apiDtoInheritor !.HierarchyRole != HierarchyRole.INTERFACE && apiDtoInheritor.HierarchyRole != HierarchyRole.ABSTRACT)
                {
                    var inheritorTypeName          = apiDtoInheritor.ToCSharpClassName();
                    var inheritorFactoryMethodName = apiDtoInheritor.ToCSharpFactoryMethodName(apiDto);

                    var methodParametersBuilder = new MethodParametersBuilder(_codeGenerationContext)
                                                  .WithParametersForApiDtoFields(DetermineFieldsToGenerateFor(apiDtoInheritor !));

                    builder.AppendLine($"{indent}public static {inheritorTypeName} {inheritorFactoryMethodName}({methodParametersBuilder.BuildMethodParametersList()})");
                    indent.Increment();
                    builder.AppendLine($"{indent}=> new {inheritorTypeName}({methodParametersBuilder.WithDefaultValueForAllParameters(null).BuildMethodCallParameters()});");
                    indent.Decrement();
                    builder.AppendLine($"{indent}");
                }
            }

            // Generate constructor
            // ReSharper disable once RedundantLogicalConditionalExpressionOperand
            if (apiDto.HierarchyRole != HierarchyRole.INTERFACE && apiDto.HierarchyRole != HierarchyRole.ABSTRACT)
            {
                var methodParametersBuilder = new MethodParametersBuilder(_codeGenerationContext)
                                              .WithParametersForApiDtoFields(apiDtoFields);

                // Empty constructor
                builder.AppendLine($"{indent}public {typeNameForDto}() {{ }}");
                builder.AppendLine($"{indent}");

                // Parameterized constructor
                if (apiDtoFields.Count > 0)
                {
                    builder.AppendLine($"{indent}public {typeNameForDto}({methodParametersBuilder.BuildMethodParametersList()})");
                    builder.AppendLine($"{indent}{{");
                    indent.Increment();
                    foreach (var apiDtoField in apiDtoFields)
                    {
                        if (FeatureFlags.GenerateAlternativeForOptionalParameterDefaultReferenceTypes && apiDtoField.Field.Type.IsCSharpReferenceType())
                        {
                            builder.AppendLine($"{indent}{apiDtoField.Field.ToCSharpPropertyName(typeNameForDto)} = {apiDtoField.Field.ToCSharpVariableInstanceOrDefaultValue(_codeGenerationContext)};");
                        }
                        else
                        {
                            builder.AppendLine($"{indent}{apiDtoField.Field.ToCSharpPropertyName(typeNameForDto)} = {apiDtoField.Field.ToCSharpVariableName()};");
                        }
                    }
                    indent.Decrement();
                    builder.AppendLine($"{indent}}}");
                    builder.AppendLine($"{indent}");
                }
            }

            // Generate properties for fields
            foreach (var apiDtoField in apiDtoFields)
            {
                builder.AppendLine(indent.Wrap(GenerateDtoFieldDefinition(typeNameForDto, apiDtoField.Field)));
            }

            // Implement IPropagatePropertyAccessPath?
            if (dtoHierarchy.Contains(nameof(IPropagatePropertyAccessPath)) && apiDto.HierarchyRole != HierarchyRole.INTERFACE)
            {
                builder.AppendLine(indent.Wrap(GenerateDtoPropagatePropertyAccessPath(apiDto, apiDtoFields)));
            }

            indent.Decrement();
            builder.AppendLine($"{indent}}}");
            return(builder.ToString());
        }