Ejemplo n.º 1
0
        internal static async Task <ApiCallRequest> BuildGetAPICallAsync <TModel>(BaseDataModel <TModel> model, EntityInfo entity, ODataQuery <TModel> oDataQuery, ApiCall apiOverride, bool forceSPORest = false, bool useLinqGet = false, bool loadPages = false)
        {
            // Can we use Microsoft Graph for this GET request?
            bool useGraph = model.PnPContext.GraphFirst && // See if Graph First is enabled/configured
                            !forceSPORest &&               // and if we are not forced to use SPO REST
                            entity.CanUseGraphGet;         // and if the entity supports GET via Graph

            // If entity cannot be surfaced with SharePoint Rest then force graph
            if (string.IsNullOrEmpty(entity.SharePointType))
            {
                useGraph = true;
            }
            // Else if we've overriden the query then simply take what was set in the query override
            else if (!apiOverride.Equals(default(ApiCall)))
            {
                useGraph = apiOverride.Type == ApiType.Graph;
            }

            if (useGraph)
            {
                return(await BuildGetAPICallGraphAsync(model, entity, oDataQuery, apiOverride, useLinqGet, loadPages).ConfigureAwait(false));
            }
            else
            {
                return(await BuildGetAPICallRestAsync(model, entity, oDataQuery, apiOverride, useLinqGet, loadPages).ConfigureAwait(false));
            }
        }
Ejemplo n.º 2
0
        internal static async Task <ApiCallRequest> BuildGetAPICallAsync <TModel>(BaseDataModel <TModel> model, EntityInfo entity, ODataQuery <TModel> oDataQuery, ApiCall apiOverride, bool forceSPORest = false, bool useLinqGet = false, bool loadPages = false)
        {
            // Can we use Microsoft Graph for this GET request?
            bool useGraph = model.PnPContext.GraphFirst && // See if Graph First is enabled/configured
                            !forceSPORest &&               // and if we are not forced to use SPO REST
                            entity.CanUseGraphGet;         // and if the entity supports GET via Graph

            // If entity cannot be surfaced with SharePoint Rest then force graph
            if (string.IsNullOrEmpty(entity.SharePointType))
            {
                useGraph = true;
            }
            // Else if we've overriden the query then simply take what was set in the query override
            else if (!apiOverride.Equals(default(ApiCall)))
            {
                useGraph = apiOverride.Type == ApiType.Graph;
            }
            else if (useGraph && useLinqGet)
            {
                // LINQ Get will based upon the defined LinqGet query + query arguments determined via entity and oDataQuery.
                // e.g. _api/web/lists or _api/web/webs
                // When there are no query arguments and when the model supports Graph (e.g. Web) then useGraph = true while
                // the queried collections (e.g. webs, lists) might not be decorated with a GraphType attribute

                if (string.IsNullOrEmpty(entity.GraphLinqGet) && !string.IsNullOrEmpty(entity.SharePointLinqGet))
                {
                    useGraph = false;
                }
            }

            if (useGraph)
            {
                return(await BuildGetAPICallGraphAsync(model, entity, oDataQuery, apiOverride, useLinqGet, loadPages).ConfigureAwait(false));
            }
            else
            {
                return(await BuildGetAPICallRestAsync(model, entity, oDataQuery, apiOverride, useLinqGet, loadPages).ConfigureAwait(false));
            }
        }
Ejemplo n.º 3
0
        private static async Task <ApiCallRequest> BuildGetAPICallRestAsync <TModel>(BaseDataModel <TModel> model, EntityInfo entity, ODataQuery <TModel> oDataQuery, ApiCall apiOverride, bool useLinqGet, bool loadPages)
        {
            string getApi = useLinqGet ? entity.SharePointLinqGet : entity.SharePointGet;

            IEnumerable <EntityFieldInfo> fields = entity.Fields.Where(p => p.Load);

            Dictionary <string, string> urlParameters = new Dictionary <string, string>();

            StringBuilder sb = new StringBuilder();

            // Only add select statement whenever there was a filter specified
            if (entity.SharePointFieldsLoadedViaExpression)
            {
                // $select
                foreach (var field in fields)
                {
                    // If there was a selection on which fields to include in an expand (via the QueryProperties() option) then add those fields
                    if (field.SharePointExpandable && field.ExpandFieldInfo != null)
                    {
                        AddExpandableSelectRest(sb, field, null, "");
                    }
                    else
                    {
                        sb.Append($"{JsonMappingHelper.GetRestField(field)},");
                    }
                }

                urlParameters.Add("$select", sb.ToString().TrimEnd(new char[] { ',' }));
                sb.Clear();
            }

            // $expand
            foreach (var field in fields.Where(p => p.SharePointExpandable))
            {
                if (entity.SharePointFieldsLoadedViaExpression)
                {
                    sb.Append($"{JsonMappingHelper.GetRestField(field)},");

                    // If there was a selection on which fields to include in an expand (via the Include() option) and the included field was expandable itself then add it
                    if (field.ExpandFieldInfo != null)
                    {
                        string path = "";
                        AddExpandableExpandRest(sb, field, null, path);
                    }
                }
                else
                {
                    if (field.ExpandableByDefault)
                    {
                        sb.Append($"{JsonMappingHelper.GetRestField(field)},");
                    }
                }
            }
            urlParameters.Add("$expand", sb.ToString().TrimEnd(new char[] { ',' }));

            oDataQuery.AddODataToUrlParameters(urlParameters, ODataTargetPlatform.SPORest);

            // REST apis do not apply a default top
            // In order to not receive all items in one request, we apply a default top
            // We don't change the original ODataQuery to avoid side effects
            if (useLinqGet && !urlParameters.ContainsKey(ODataQuery <TModel> .TopKey))
            {
                urlParameters.Add(ODataQuery <TModel> .TopKey, model.PnPContext.GlobalOptions.HttpSharePointRestDefaultPageSize.ToString());
            }

            sb.Clear();

            // Build the API call
            string baseApiCall = "";

            if (apiOverride.Equals(default(ApiCall)))
            {
                baseApiCall = $"{model.PnPContext.Uri.AbsoluteUri.TrimEnd(new char[] { '/' })}/{getApi}";
            }
            else
            {
                baseApiCall = $"{model.PnPContext.Uri.AbsoluteUri.TrimEnd(new char[] { '/' })}/{apiOverride.Request}";
            }

            // Parse tokens in the base api call
            baseApiCall = await ApiHelper.ParseApiCallAsync(model, baseApiCall).ConfigureAwait(false);

            sb.Append(baseApiCall);

            // Build the querystring parameters
            NameValueCollection queryString = HttpUtility.ParseQueryString(string.Empty);

            foreach (var urlParameter in urlParameters.Where(i => !string.IsNullOrEmpty(i.Value)))
            {
                // Add key and value, which will be automatically URL-encoded, if needed
                queryString.Add(urlParameter.Key, urlParameter.Value);
            }

            // Build the whole URL
            if (queryString.AllKeys.Length > 0)
            {
                // In .NET Framework to ToString() of a NameValueCollection will use HttpUtility.UrlEncodeUnicode under
                // the covers resulting in issues. So we decode and encode again as a workaround. This code produces the
                // same result when used under .NET5/Core versus .NET Framework
                sb.Append($"?{queryString.ToEncodedString()}");
            }

            // Create ApiCall instance and call the override option if needed
            var call = new ApiCallRequest(new ApiCall(sb.ToString(), ApiType.SPORest, loadPages: loadPages));

            if (model.GetApiCallOverrideHandler != null)
            {
                call = await model.GetApiCallOverrideHandler.Invoke(call).ConfigureAwait(false);
            }

            return(call);
        }