Development

Why my action is not available through WebApi?

Recently I was working on task where I wanted to use Actions through JavaScript. It was a pretty usual task until I came calling of an action through WebApi. I was able to call that action through SOAP endpoint but every call through WebApi threw an error with message “Resource not found for the segment ‘new_MyAction’.

My action had couple of simple (strings and integers) input parameters and had to return one string and one EntityCollection in result. To make action available through WebApi I had to remove all outputs except EntityCollection.

Let’s separate all types of arguments into two groups – simple (boolean, datetime, decimal, float, integer, money, picklist, string) and complex (EntityReference, Entity, EntityCollection). You can have any combination of simple output parameters or single complex output parameter to make your action available for WebApi. In other words if you combine complex output parameter with any other one (including another complex output parameter) your action becomes unavailable for WebApi calls.

To check availability of your action you can use metadata url:

CRM Online –  https://yourorgname.crm.dynamics.com/api/data/v8.1/$metadata

On-Premise with IFD configured – https://yourorgname.yourdomain.com/api/data/v8.1/$metadata

On-Premise without IFD configured – http://yourcrmserver/yourorgname/api/data/v8.1/$metadata

Just open metadata url in browser, wait till page is loaded and hit Ctrl-F to find action you want to check:

ActionAvailability

21 Comments

  1. Hi Andriy,

    Thanks for the info, have you tried to open the issue with Microsoft regarding this?

    1. Hello Pavel,
      I have not. May be it’s a good idea to post it to CRMIdeas portal. I was able to find a workaround – I just added all additional information I need as a last element of collection and it worked fine.

  2. Has anyone tried to return one EntityCollection from the CustomAction with different entity types ?
    I’m doing that, but I get this error when calling the Custom Action (Returning an EntityCollection with just one entity type worked fine):

    “error”:{
    “code”:””,”message”:”‘select’ and ‘expand’ cannot be both null or empty.”,”innererror”:{
    “message”:”‘select’ and ‘expand’ cannot be both null or empty.”,”type”:”System.ArgumentException”,”stacktrace”:” at System.Web.OData.Query.SelectExpandQueryOption..ctor(String select, String expand, ODataQueryContext context, ODataQueryOptionParser queryOptionParser)\r\n at Microsoft.Crm.Extensibility.OData.CrmODataEntityTypeSerializer.CreateSelectExpandNode(EntityInstanceContext entityInstanceContext)\r\n at System.Web.OData.Formatter.Serialization.ODataEntityTypeSerializer.WriteEntry(Object graph, ODataWriter writer, ODataSerializerContext writeContext, IEdmTypeReference expectedType)\r\n at System.Web.OData.Formatter.Serialization.ODataFeedSerializer.WriteFeed(IEnumerable enumerable, IEdmTypeReference feedType, ODataWriter writer, ODataSerializerContext writeContext)\r\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content, HttpContentHeaders contentHeaders)\r\n at System.Web.OData.Formatter.ODataMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()”
    }

    1. Hello,
      Yes, I experienced similar issue as well. Everything worked fine when I used SOAP calls but for WebApi it doesn’t work well.
      I ended up with changing output parameter to string and I serialized response as a JSon string and deserialized it back on client side. Worked like a charm.

  3. I will vote this up as well.
    We are seeing issues with our custom actions not showing up in the Metadata for the webapi. Only the actions which were imported from a solution do not show up in the Web Api metadata. If the action is created in the CRM instance, it shows up in the metadata.

  4. Hi Andrii. Not sure how you solved this. I have a bound action and no matter how I try to address it, I get the same error “Resource not found for the segment ‘cfc_ActivateaQuote'”. The URL’s I have passed in are:
    “https://cfccrm.crm.dynamics.com/api/data/v9.0/Microsoft.Dynamics.CRM.cfc_ActivateaQuote”
    “https://cfccrm.crm.dynamics.com/api/data/v9.0/cfc_ActivateaQuote”

    I looked at the metadata as suggested and do not see the Action name anywhere.

    1. Hello Clint,
      Bound actions are called in a bit different way, check following post – http://dotnet-posts.blogspot.com/2016/10/calling-dynamics-crm-2016-actions-using.html
      It’s weird that you can’t see it in metadata. I believe that issue was addressed already. What you can try – delete action and create it from scratch. Sometimes publishing happens immediately, sometimes it happens in hour or so. Anyway I believe you can reach Microsoft support and open a support ticket to get help.
      Thanks,
      Andrew

      1. Thanks for getting back to me. That blog contains pretty much the JavaScript I am using. I did find something very interesting though. I am so glad you suggested checking the metadata first. It definately was not showing up. I had tried republishing a few times. It never showed up. Then I created a Rollup field and published the solution (showing the customer how to replace a plugin left over from CRM2013). I rechecked the metadata today, and the Action is there. Strange, no?

        I have a theory: There needs to be some other customizations present besides the Action when you publish the solution for the Action to show up. Sounds like a bug, but this may be the workaround.

        I am still working through this as it’s now complaining “resource not found for the segment action_name”, but I know it’s there.

  5. Good afternoon, actually I have the issue that I can’t call any of my customs actions.

    I can see it there in the list of all the metadata https://yourorgname.yourdomain.com/api/data/v8.1/$metadata
    but when I try to call it, I got the error message No HTTP resource was found that matches the request URI.

    This is how I make the call
    https://mscrm.XX.YYYYY.com/MSCRM-Q/api/data/v8.0/opportunities(D0138CA8-1F1E-E911-810A-005056BE0CB9)/Microsoft.Dynamics.CRM.new_GetProjectDefaults

    Do you know how can I do to fix this issue?
    Thanks.

    1. HI Victor

      I am getting the same issue. Did you get the solution? If yes please share it.

  6. Hi Andrew Butenko,

    I am trying to call the custom action from web API. I checked the metadata.Action present in the metadata. However, I am not able to call from javascript. It’s GET web API call and it for the entity set to none(global).

    1. Hello,
      Do you use Online or onprem? What version are you on? Is it global or entity specific action, please post code you use.
      Thanks,
      Andrew

      1. I am using CRM 2016 on premise 8.1.1.1005 . It’s a global entity. This is my javaScript to call the custom action, Name as dycdpts_potentialConflict which has no parameters. I just removed for testing purpose. With parameters I have the same issue.
        Here is my code
        _this.getConflictAppointments = function (enrollmentList, startDate, endDate, groupId, selectedSchedule) {

        var getStartEndDateTime = function () {

        var startEndDateTime = { startDateTime: startDate, endDateTime: endDate };
        if (endDate === null) endDate = startDate;
        if (selectedSchedule != null) {
        //get hr
        var startTimeHr = selectedSchedule.startTime.split(“:”)[0];
        var endTimeHr = selectedSchedule.endTime.split(“:”)[0];
        //get Min
        var startTimeMin = selectedSchedule.startTime.split(“:”)[1].split(” “)[0];
        var endTimeMin = selectedSchedule.endTime.split(“:”)[1].split(” “)[0];
        // Meridiem
        var startTimeMeridiem = selectedSchedule.startTime.split(“:”)[1].split(” “)[1];
        var endTimeMeridiem = selectedSchedule.endTime.split(“:”)[1].split(” “)[1];

        //covert the 12 hrs to 24 hrs

        if (startTimeMeridiem == “PM” && startTimeHr < 12) startTimeHr = parseInt(startTimeHr) + 12;
        if (startTimeMeridiem == "AM" && startTimeHr == 12) startTimeHr = parseInt(startTimeHr) – 12;
        if (endTimeMeridiem == "PM" && endTimeHr < 12) endTimeHr = parseInt(endTimeHr) + 12;
        if (endTimeMeridiem == "AM" && endTimeHr == 12) endTimeHr = parseInt(endTimeHr) – 12;
        //generate the date
        var startDay = startDate.getDate();
        var startMonth = startDate.getMonth();
        var startYear = startDate.getFullYear();
        // var startDateTime = new Date(startYear, startMonth, startDay, startTimeHr, startTimeMin, 00, 00);
        var endDay = endDate.getDate();
        var endMonth = endDate.getMonth();
        var endYear = endDate.getFullYear();
        // var endDateTime = new Date(endYear, endMonth, endDay, endTimeHr, endTimeMin, 00, 00);

        var startDateTime = startYear + "-" + (startMonth + 1) + "-" + startDay + "T" + startTimeHr + ":" + startTimeMin + ":" + "00";
        var endDateTime = endYear + "-" + (endMonth + 1) + "-" + endDay + "T" + endTimeHr + ":" + endTimeMin + ":" + "00";
        return startEndDateTime = { startDateTime: startDateTime, endDateTime: endDateTime };
        }
        }

        var participantEnrollment = [];
        // var participantIds= [];
        var scheduleDateTime=getStartEndDateTime();
        enrollmentList.map(function(enrollment) {
        //create obj
        participantIds = enrollment.participantId+",";

        });
        participantEnrollment.push = ({
        activityscheduleStartTime: scheduleDateTime.startDateTime,
        activityScheduleEndTime: scheduleDateTime.endDateTime,
        groupId: groupId,
        selectedScheduleId: selectedSchedule.scheduleId,
        participantIds: participantIds
        });

        var actionUri = "/dycdpts_potentialConflict";

        return new Promise(function(resolve, reject) {
        SDK.request("GET", actionUri, null, true, 5000).then(function (request) {

        });
        });

        };

        I am getting the error
        {
        "error":{
        "code":"","message":"No HTTP resource was found that matches the request URI 'https://dent-crm-w01.dycd.nycnet/DYCDCRMAttendance/api/data/v8.1/dycdpts_potentialConflict&#039;."
        }
        }

        We are facing this issue since from the last 4 to 5 weeks. Previously I had the same scenario where I created the custom action and passed the parameters. It's working fine. code for this.Its also global entity with string and entity reference type parameters
        _this.createAttendance= function(line, index, value, isMarkAll, date, resolve) {
        var actionUri = "/dycdpts_createAttendance";
        var appointment = line.apps[index];
        var parameters = {};
        parameters.enrollmentId = line.enrollmentId;
        parameters.appointmentId = appointment.appointmentId;

        parameters.attendanceValue = (value == null ? null: ((value == true) ? "100000000": "100000001"));
        //blockUIConfig.message = "get Create attendance…455555555555555555555555555555……………..";
        blockUI.start();

        return new Promise(function (resolve, reject) {

        SDK.request("POST", actionUri, parameters).then(function(request) {
        blockUI.stop();
        if (request.response !== ""||request.response!==null)
        var obj = JSON.parse(request.response);
        if (obj !== null) {
        var attendanceId = obj["dycdpts_participantattendanceid"];
        _this.getAttendance(attendanceId).then(function(data) {
        // blockUI.stop();
        if (line && line.programAreaName !== "COMPASS" && !value && line.registrationEnrollmentDate) {
        _this.ReValidateRegistrationEnrollmentDate(line);
        }
        resolve(data);
        });

        }

        }).catch(function (error) {
        blockUI.stop();
        reject(error.message);
        });
        });

        }

        1. Good morning, I still have this issue in my onpremise v8.1 and even in my v8.2

          Even creating a simple Action without parameters and with only one step to stop the workflow with a customized message, I got the error:

          {
          “error”: {
          “code”: “”,
          “message”: “Resource not found for the segment ‘ActionName’.”,
          “innererror”: {
          “message”: “Resource not found for the segment ‘ActionName’.”,
          “type”: “Microsoft.OData.Core.UriParser.ODataUnrecognizedPathException”,
          “stacktrace”: ” at Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.CreateFirstSegment(String segmentText)\r\n at Microsoft.OData.Core.UriParser.Parsers.ODataPathParser.ParsePath(ICollection`1 segments)\r\n at Microsoft.OData.Core.UriParser.Parsers.ODataPathFactory.BindPath(ICollection`1 segments, ODataUriParserConfiguration configuration)\r\n at Microsoft.OData.Core.UriParser.ODataUriParser.Initialize()\r\n at System.Web.OData.Routing.DefaultODataPathHandler.Parse(IEdmModel model, String serviceRoot, String odataPath, ODataUriResolverSetttings resolverSettings, Boolean enableUriTemplateParsing)\r\n at System.Web.OData.Routing.DefaultODataPathHandler.Parse(IEdmModel model, String serviceRoot, String odataPath)\r\n at Microsoft.Crm.Extensibility.OData.CrmODataPathHandler.Parse(IEdmModel model, String serviceRoot, String odataPath)”
          }
          }
          }

        2. Victor,
          If everything is correct in code I see only the one way – open a ticket with Microsoft and ask for support.
          Andrew

        3. I would recommend to troubleshoot all calls using PostMan first and then went to JS.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.