Krillehbg Krillehbg - 3 months ago 26
C# Question

Problems with servicestack and typelinks

I have problems with gerenating types, it returns error
500 - InvalidDataException

I can't understand whats wrong as my project builds fine and API works.

None of the types works except the metadata

https://testapi.bokamera.se/types/

Please help as i'm stuck

Regards Kristian

Here you can see my call using Postman
enter image description here

and here you can see my DTO causing the problem

namespace BokaMera.API.ServiceModel.Dtos
{
[Route("/customfields",
Verbs = "GET",
Summary = "Find custom fields",
Notes =
"Find custom fields defined for the bookings that the current admin user is authorized to view."
)]
[ApiResponse(HttpStatusCode.Unauthorized, "You were unauthorized to call this service")]
[ApiResponse(HttpStatusCode.Forbidden, "You have too low privilegies to call this service")]
public class CustomFieldQuery :
QueryBase<CustomFieldConfig, CustomFieldQueryResponse>
{
[ApiMember(
Description =
"One or multiple id's of custom fields to find",
ParameterType = "query",
IsRequired = false)]
public int[] Ids { get; set; }

[ApiMember(
Description =
"Company id to find custom fields for",
ParameterType = "query",
IsRequired = false)]
public Guid? CompanyId { get; set; }

[ApiMember(
Description =
"Table to which the custom field belongs to",
ParameterType = "query",
IsRequired = false)]
public string Table { get; set; }

[ApiMember(
Description =
"Active or removed fields, empty parameter includes both",
ParameterType = "query",
IsRequired = false)]
public bool? Active { get; set; }
}

public class CustomFieldQueryResponse
{
[ApiMember(Description = "Custom field id")]
public int Id { get; set; }

[ApiMember(Description = "Reference to company that owns the custom field configuration")]
public Guid CompanyId { get; set; }

[ApiMember(Description = "Group id")]
public int? GroupId { get; set; }

[ApiMember(Description = "Config id")]
public int ConfigId { get; set; }

[ApiMember(Description = "Configuration name. Example: \"Number of persons\".")]
public string ConfigName { get; set; }

[ApiMember(Description = "Field width. Example: 20")]
public int Width { get; set; }

[ApiMember(Description = "Column in database where to store the information. Example: \"TextField1\"")]
public string Column { get; set; }

[ApiMember(Description = "Custom field description. Example: \"For how many persons is this booking?\"")]
public string Description { get; set; }

[ApiMember(Description = "Data field of custom field. Valid values are: TextBox, ... Example: \"TextBox\"")]
public string DataType { get; set; }

[ApiMember(Description = "Default value of the field. Example: \"3\"")]
public string DefaultValue { get; set; }

[ApiMember(Description = "Determines if the field is required to have a value or not")]
public bool Required { get; set; }

[ApiMember(Description = "Error message shown to the user if the field data is required but not entered")]
public string MandatoryErrorMessage { get; set; }

[ApiMember(Description = "Max lenght of the field")]
public int MaxLength { get; set; }

[ApiMember(Description = "")]
public bool MultipleLineText { get; set; }

[ApiMember(Description = "Regular expression used for validation of the field")]
public string RegEx { get; set; }

[ApiMember(Description = "Error message shown if the regular expression validation failed")]
public string RegExErrorMessage { get; set; }

[ApiMember(Description = "If the custom field is active or have been removed")]
public bool Active { get; set; }

[ApiMember(Description = "Table to which the field belongs")]
public string Table { get; set; }

[ApiMember(Description = "")]
public List<CustomFieldLookupResponse> Values { get; set; }
}


[Alias("V_FreeFieldFieldLookUp")]
public class CustomFieldLookupResponse
{
[PrimaryKey]
[Alias("FieldLookupId")]
public int? Id { get; set; }

[Alias("FreeFieldId")]
public int CustomFieldId { get; set; }

[Alias("FieldlookupActive")]
public bool? Active { get; set; }

[Alias("FieldLookupGroupId")]
public int GroupId { get; set; }

[Alias("FieldlookupSortOrder")]
public int? SortOrder { get; set; }

[Alias("FieldlookupValue")]
public string Value { get; set; }
}




//Used when sending in values on a DTO request object to the services to save on the tables.
public class CustomFieldDataValue
{
public int Id { get; set; }
public string Column { get; set; }
public string Value { get; set; }

}


//Used to list all values on a DTO response object
public class CustomFieldData
{
public int Id { get; set; }
public string Column { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Value { get; set; }
}

//Used when post or put values for different DTOS, see example Resource Dtos
public class AddCustomField
{
public int Id { get; set; }
public string Value { get; set; }

}


}

And my service

namespace BokaMera.API.ServiceInterface.Services
{
public class CustomFieldService : AppServiceBase
{
public IAutoQueryDb AutoQuery { get; set; }

[Authenticate]
[RequiredRole(Role.ApplicationAdmin)]
public object Get(CustomFieldQuery request)
{
// Get the autoquery that we will append to
var q = AutoQuery.CreateQuery(request, Request.GetRequestParams());

// The user can only see his/her own time exceptions
q = q.Where(te => te.CompanyId == UserSession.CompanyId);

// Execute counts and return the query response
var response = AutoQuery.Execute(request, q);
return response;
}
}


}

Answer

If you were on v4.0.58, it had an issue with Add ServiceStack Reference which can be resolved by upgrading to any release after that.

The issue with your DTOs was because they contained illegal " character in the Metadata attributes, i.e:

[ApiMember(Description = "Configuration name. Example: \"Number of persons\".")]
public string ConfigName { get; set; }

We validate metadata attributes to prevent an attacker from potentially injecting illegal data that they could use to generate malicious in Service consumers.

So to prevent the error you can remove double quotes (") from strings in your metadata attributes, replacing them with single quotes (') is fine, otherwise you can disable token verification in your AppHost.Configure() with:

NativeTypesFeature.DisableTokenVerification = true;

Incidentally Exception details from Code Generation will be more visible in the next release from this commit, so it will be clearer to tell what the error was.


Deprecated Warnings

Please take note of the Deprecation messages (also covered in Breaking changes in each Release Notes). QueryBase has been renamed to QueryDb, e.g:

public class CustomFieldQuery :
    QueryDb<CustomFieldConfig, CustomFieldQueryResponse>

Also it's better for your custom AutoQuery implementations to pass the entire IRequest instead of just the parameters, e.g:

var q = AutoQuery.CreateQuery(request, base.Request);

This has the same behavior except it also allows this AutoQuery Service to participate in Multitenancy requests.