Skip to content

Added structural types and properties documentation properties#2236

Open
henning-krause wants to merge 391 commits into
OData:masterfrom
henning-krause:master
Open

Added structural types and properties documentation properties#2236
henning-krause wants to merge 391 commits into
OData:masterfrom
henning-krause:master

Conversation

@henning-krause

Copy link
Copy Markdown

Issues

This PR adds documentation capabilities to the OdataConventionModelBuilder (as requested by #1732).

Description

The changes add new properties Description and LongDescription to StructualTypeConfiguration and PropertyConfiguration. Additionally, a new Attribute DescriptionAttribute is introduced to allow the developer to set the description via attributes on properties and classes.

Using this, one can now utilize the C# XML documentation (Using the DocXml - C# XML documentation reader) for the entities:

private static void OnModelCreating(ODataConventionModelBuilder builder)
{
	var reader = new DocXmlReader();
	
	foreach (var type in builder.StructuralTypes)
	{
		var comment = reader.GetTypeComments(type.ClrType);
		if (comment != null)
		{
			if (!string.IsNullOrEmpty(comment.Summary)) type.Description = comment.Summary;
			if (!string.IsNullOrEmpty(comment.Remarks)) type.LongDescription = comment.Remarks;
		}

		foreach (var property in type.Properties)
		{
			var propertyComment = reader.GetMemberComments(property.PropertyInfo);
			if (propertyComment != null)
			{
				if (!string.IsNullOrEmpty(propertyComment.Summary)) property.Description = propertyComment.Summary;
				if (!string.IsNullOrEmpty(propertyComment.Remarks)) property.LongDescription = propertyComment.Remarks;
			}
		}
	}
}

When the metadata is emitted, the proper Odata `Description` and `LongDescription` metadata annotations are included in the document.

Checklist (Uncheck if it is not completed)

  • Test cases added
  • Build and test with one-click build and test script passed

Additional work necessary

If the PR is accepted, I would add this functionality to functions and actions and their parameters.

xuzhg and others added 30 commits March 29, 2018 14:38
the description and the QueryFilter itself.
the EntityId. The response code is not set properly until after
ExecuteResultAsync() is completed.
key is not present in the SerializableError.

Convert the errors in SerializableError into ODataErrorDetail
collection.
…bound

is either ODataQueryOptions or ODataQueryOptions<T>.
if a filter of the same type is already present in the Filters list.

Modify QueryFilterProvider to apply of a global query filter
if the return type is a Task<> returning a collection and if the
return type is derived from single result.
…ataPathRouteConstraintTest.

RFC3986 specifies "[" and "]" and gen-delims in BNF notation in section 2.2 but section 3.2.2
specifies that the are only valid in a Uri as part of an IPV6 host. Therefore, they are not
valid in any part of a Uri, which is how the tests use _stringsLegalEverywhere.
…rate is:

AspNet    : 4648 pass, 0 fail - 100% enabled, 100% pass
AspNetCore: 4424 pass, 0 fail - 95% enabled, 100% pass

This change:

1.) Fixes DelayLoadFilterProvider so it works.
2.) Adds coreBuilder.AddDataAnnotations() to enable DataAnnotation validation.
3.) Makes the default action "Get"
4.) Makes Created() and BadRequest() return action results.
5.) Includes route name in GetServiceRootUri()
6.) Fixes LowerCamelCaseTest to expect BadResult() now that ODataQueryOptions skips parameter validation.
7.) Disables CRUDEntitySetShouldWork() since unicode values in headers are not supported in Kestrel.
8.) Modifies IsofFunctionTests to expect an HttpRequestException since an error occurs during formatting
    after headers has been sent and AspNetCore returns HttpRequestException in this case.
9.) Modifies ODataValueProviderTests to inject an Id instead of an object due to AspNetCore parameter
    handle; this also work in AspNet.
10.) Fixes tests in DeltaOfTValidationTests, ComplextTypeCollectionTests, JsonSingleResultExpandTests,
     ODataQueryOptionsTests, QueryFuzzingTests, ValidatorTests, and DeltaOfTValidationTests
11.) Enables tests in ContainmentTests, DeltaTests, SecurityTests, PropertyTestsUsingConventionModelBuilder,
     CustomFilterValidator, AddRelatedObjectTests, SingletonTests
into account parameters types the bind using custom binders.
1.) Modify Match_ReturnsTrue_IfODataPathCanBeParsed to handle platform-specific differences
    in route constraint.
2.) Test ODataRoute without comparing to HttpRoute due to platform differences in HttpRoute.
3.) Modify EntityTypeFunction to return error based on ModelState instead of relying on
    exception handling which is platform dependant.
crgolden and others added 14 commits May 8, 2020 09:40
…erty (OData#2160)

* Fix logic for patching entity with complex type dynamic property

* Support patching of complex type dynamic property in a structured type plus tests

* Use string.IsNullOrWhiteSpace

Co-authored-by: John Gathogo <jogathog@microsoft.com>
Add System.Diagnostics.EventLog into ASP.NET Core 3.x E2E test project
* Fix bug 2177 - encode DateTimeOffset value in generated skip token

* Fix bug 2177 - encode all types of parameters in generated skiptoken
* Add null check to TruncatedCollection.

* Add test.

Co-authored-by: Brecht Debaere <Brecht.Debaere@spray.com>
@xuzhg

xuzhg commented Jul 23, 2020

Copy link
Copy Markdown
Member

@henning-krause Thanks for contribution. Just For your information, did you see "OData/ModelBuilder#9".
Can we combine your PR with the whole vocabulary configuration?

@henning-krause

Copy link
Copy Markdown
Author

@xuzhg By all means, do that. Can I help to speed things up?

@henning-krause

Copy link
Copy Markdown
Author

@xuzhg since OData/ModelBuilder#9 has been merged, is there a chance to merge this also? I don't see anything of my code in the referenced PR.

@henning-krause

Copy link
Copy Markdown
Author

@xuzhg Any news on this PR?

@mikepizzo

Copy link
Copy Markdown
Contributor

Hi @henning-krause -happy new year!

Thanks for your contribution, and sorry to have taken so long to follow up.

OData/ModelBuilder#9 provides the ability to implement patterns such as:

	var comment = reader.GetTypeComments(type.ClrType);
	if (comment != null)
	{
		if (!string.IsNullOrEmpty(comment.Summary)) type.HasDescription(comment.Summary);
		if (!string.IsNullOrEmpty(comment.Remarks)) type.HasLongDescription(comment.Remarks);
	}

Is this sufficient for what you're trying to do?

@henning-krause

Copy link
Copy Markdown
Author

Hi @mikepizzo,

I've just upgraded my solution to the latest odata libs (Microsoft.AspNet.OData 7.5.4 and Microsoft.OData.Core and Microsoft.OData.Edm 7.8.1) but I can't find the methods you're refering to.

I'm working with the ODataConventionModelBuilder and I don't see those methods, at least not on things like

  builder.EntitySet<Role>("Roles");

It seems that I'm missing something here.

@mikepizzo

Copy link
Copy Markdown
Contributor

It looks like OData/ModelBuilder#9 hasn't been backported to AspNet.OData 7.x. Let's try and do that first, so that developers using this feature in 7.x will have a consistent experience in 8.x.

@g2mula -- Can you look at porting your OData/ModelBuilder#9 PR to this branch?


if (edmType is IEdmStructuredType structuredType)
{
foreach (var entry in structuredType.DeclaredProperties.Join(structuralType.Properties, p => p.Name, p => p.Name, (property, configuration) => new {property, configuration}))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, I think that maybe ToDictionary is more appropriate than Join. Wouldn't this be equivalent functionality, but a bit more optimized?

var structuredTypeProperties = structuredType.DeclaredProperties.ToDictionary(p => p.Name, p => p);
foreach (var structuralTypeProperty in structuralType.Properties)
{
  if (!structuredTypeProperties .TryGetValue(structuralTypeProperty.Name, out var structuredTypeProperty)
  {
    continue;
  }

  if (!string.IsNullOrEmpty(structuralTypeProperty.Description)
  {
    model.SetDescriptionAnnotation(structuredTypeProperty, structuralTypeProperty.Description);
  }

  if (!string.IsNullOrEmpty(structuralTypeProperty.LongDescription)
  {
    model.SetDescriptionAnnotation(structuredTypeProperty, structuralTypeProperty.LongDescription);
  }
}

public string LongDescription
{
get => _longDescription;
set => _longDescription = value ?? throw Error.PropertyNull();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that throwing is appropriate here because _longDescription will be null by default, so we aren't really protecting against anything

@xuzhg xuzhg force-pushed the master branch 2 times, most recently from 4c43a84 to ddfd3dd Compare May 29, 2026 01:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.