How to build EDM model for OData Web API in runtime?
Ok, so I've figured out an answer to this problem.
I've written my own OData model builder that uses types from Microsoft.Data.Edm.Library namespace (EdmModel, EdmEntityType and so on).
Example:
public IEdmModel GetEdmModel()
{
EdmModel model = new EdmModel();
EdmEntityContainer container = new EdmEntityContainer(Namespace, "DefaultContainer");
model.AddElement(container);
model.SetIsDefaultEntityContainer(container, isDefaultContainer: true);
EdmEntityType edmType = new EdmEntityType(Namespace, "Foo");
EdmStructuralProperty idProp = edmType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Int32), false);
edmType.AddKeys(idProp);
сontainer.AddEntitySet("MyEntitySet", edmType);
model.SetDataServiceVersion(new Version(3, 0, 0, 0));
model.SetMaxDataServiceVersion(new Version(3, 0, 0, 0));
return model;
}
I solved this problem like that,
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "WebAPI";
builder.ContainerName = "DefaultContainer";
builder.EnableLowerCamelCase();
foreach (Type item in GetTypesInNamespace(System.Reflection.Assembly.Load("ProjectDLL"), "NamespaceOfModels"))
{
//My models have a key named "Id"
if (item.GetProperty("Id") == null)
continue;
EntityTypeConfiguration entityType = builder.AddEntityType(item);
entityType.HasKey(item.GetProperty("Id"));
builder.AddEntitySet(item.Name,entityType);
}
return builder.GetEdmModel();
}
Getting types in Sample Namespace
private static Type[] GetTypesInNamespace(System.Reflection.Assembly assembly, string nameSpace)
{
return assembly.GetTypes()
.Where(t => String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal))
.ToArray();
}