Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OData 6.0 How to have both UnqualifiedODataUriResolver and StringAsEnumResolver? #856

Closed
Mytza opened this issue Nov 22, 2016 · 4 comments
Closed

Comments

@Mytza
Copy link

Mytza commented Nov 22, 2016

Hi,

I am having problem enabling StringAsEnumResolver and UnqualifiedODataUriResolver.
Before migrating to Odata 6.0 i was using:
configuration.EnableUnqualifiedNameCall(true);
configuration.EnableEnumPrefixFree(true);

How can i achieve this with OData 6.0 ?

I tried:

 configuration.MapODataServiceRoute(
                "ODataRoute",
                null,
                builder =>
                    builder.AddService(ServiceLifetime.Singleton, sp => BuildModel())
                        .AddService<IEnumerable<IODataRoutingConvention>>(ServiceLifetime.Singleton, sp =>
                                ODataRoutingConventions.CreateDefaultWithAttributeRouting("ODataRoute", configuration))
                        .AddService<ODataUriResolver>(ServiceLifetime.Singleton, sp => new StringAsEnumResolver())
                        .AddService<ODataUriResolver>(ServiceLifetime.Singleton, sp => new UnqualifiedODataUriResolver())
                        .AddService<ODataSerializerProvider, AuthorizationODataSerializerProvider>(ServiceLifetime.Singleton)
            );

But as both are of type ODataUriResolver, this is not working.
I looked in the unit tests but i couldn't find any example.

Thanks in advance,
Mihai

@Mytza
Copy link
Author

Mytza commented Nov 29, 2016

I managed to set-up a work-arround.
There is an internal class in System.Web.OData called UnqualifiedCallAndEnumPrefixFreeResolver.
Based on that i created my own, my only addition to this was also to handle ResolveUnboundOperations from ODataUriResolver.

Sample code is:

public class UnqualifiedCallAndEnumPrefixFreeResolver : ODataUriResolver
    {
        private readonly StringAsEnumResolver _stringAsEnum = new StringAsEnumResolver();
        private readonly UnqualifiedODataUriResolver _unqualified = new UnqualifiedODataUriResolver();

        private bool _enableCaseInsensitive;

        public override bool EnableCaseInsensitive
        {
            get { return this._enableCaseInsensitive; }
            set
            {
                this._enableCaseInsensitive = value;
                _stringAsEnum.EnableCaseInsensitive = this._enableCaseInsensitive;
                _unqualified.EnableCaseInsensitive = this._enableCaseInsensitive;
            }
        }

        #region UnqualifiedODataUriResolver

        public override IEnumerable<IEdmOperation> ResolveBoundOperations(IEdmModel model, string identifier,
            IEdmType bindingType)
        {
            return _unqualified.ResolveBoundOperations(model, identifier, bindingType);
        }

        public override IEnumerable<IEdmOperation> ResolveUnboundOperations(IEdmModel model, string identifier)
        {
            return _unqualified.ResolveUnboundOperations(model, identifier);
        }

        #endregion

        #region StringAsEnumResolver

        public override void PromoteBinaryOperandTypes(BinaryOperatorKind binaryOperatorKind,
            ref SingleValueNode leftNode, ref SingleValueNode rightNode, out IEdmTypeReference typeReference)
        {
            _stringAsEnum.PromoteBinaryOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode, out typeReference);
        }

        public override IEnumerable<KeyValuePair<string, object>> ResolveKeys(IEdmEntityType type,
            IDictionary<string, string> namedValues, Func<IEdmTypeReference, string, object> convertFunc)
        {
            return _stringAsEnum.ResolveKeys(type, namedValues, convertFunc);
        }

        public override IEnumerable<KeyValuePair<string, object>> ResolveKeys(IEdmEntityType type,
            IList<string> positionalValues, Func<IEdmTypeReference, string, object> convertFunc)
        {
            return _stringAsEnum.ResolveKeys(type, positionalValues, convertFunc);
        }

        public override IDictionary<IEdmOperationParameter, SingleValueNode> ResolveOperationParameters(
            IEdmOperation operation, IDictionary<string, SingleValueNode> input)
        {
            return _stringAsEnum.ResolveOperationParameters(operation, input);
        }

        #endregion
    }

Maybe it would be good to make the class public, and add also this addition.

@biaol-odata biaol-odata added the P4 label May 31, 2017
@biaol-odata
Copy link
Contributor

biaol-odata commented May 31, 2017

Hi Mytza, thanks for providing the workaround. It will be great if you can also provide your solution to the global stackoverflow.com so that the OData community can benefit from this.

@Mytza
Copy link
Author

Mytza commented Jun 6, 2017

Hi,
I also answered a question on stackoverflow.com, you can find it here

@victorperez2911
Copy link

If someone needs to use AlternateKeys along with UnqualifiedODataUriResolver.

using Microsoft.OData.Edm;
using Microsoft.OData.UriParser;
using System;
using System.Collections.Generic;

namespace PBSWebServerAPI.Util
{
    /// <summary>
    /// Implementation for resolving the alternate keys and Resolver that supports bound function calls..
    /// </summary>
    public class CustomODataUriResolver : ODataUriResolver
    {
        
        /// <summary>
        /// Model to be used for resolving the alternate keys.
        /// </summary>
        private readonly IEdmModel model;

        private readonly AlternateKeysODataUriResolver alternateKeysODataUriResolver;
        private readonly UnqualifiedODataUriResolver unqualifiedODataUriResolver;

        public CustomODataUriResolver(IEdmModel model)
        {
            this.model = model;
            alternateKeysODataUriResolver = new AlternateKeysODataUriResolver(model);
            unqualifiedODataUriResolver = new UnqualifiedODataUriResolver();
        }
        
        #region Implementa AlternateKeysODataUriResolver

        /// <summary>
        /// Resolve keys for certain entity set, this function would be called when key is specified as name value pairs. E.g. EntitySet(ID='key')
        /// </summary>
        /// <param name="type">Type for current entityset.</param>
        /// <param name="namedValues">The dictionary of name value pairs.</param>
        /// <param name="convertFunc">The convert function to be used for value converting.</param>
        /// <returns>The resolved key list.</returns>
        public override IEnumerable<KeyValuePair<string, object>> ResolveKeys(IEdmEntityType type, IDictionary<string, string> namedValues, Func<IEdmTypeReference, string, object> convertFunc)
        {
            var result = alternateKeysODataUriResolver.ResolveKeys(type, namedValues, convertFunc);
            return result;
        }


        #endregion

        #region Implementa UnqualifiedODataUriResolver

        /// <summary>
        /// Resolve unbound operations based on name.
        /// </summary>
        /// <param name="model">The model to be used.</param>
        /// <param name="identifier">The operation name.</param>
        /// <returns>Resolved operation list.</returns>
        public override IEnumerable<IEdmOperation> ResolveUnboundOperations(IEdmModel model, string identifier)
        {
            var result = unqualifiedODataUriResolver.ResolveUnboundOperations(model, identifier);
            return result;
        }


        /// <summary>
        /// Resolve bound operations based on name.
        /// </summary>
        /// <param name="model">The model to be used.</param>
        /// <param name="identifier">The operation name.</param>
        /// <param name="bindingType">The type operation was binding to.</param>
        /// <returns>Resolved operation list.</returns>
        public override IEnumerable<IEdmOperation> ResolveBoundOperations(IEdmModel model, string identifier, IEdmType bindingType)
        {
            var result = unqualifiedODataUriResolver.ResolveBoundOperations(model, identifier, bindingType);
            return result;
        }


        #endregion
        
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants