Consume WebService - "Path property mus be set before [...]"

JutJut Member Posts: 72
edited 2009-04-10 in NAV Three Tier
Good morning,

I am working a little bit with the NAV 2009 Marketing Demo and I was trying to use the Webservices that are provided by NAV. At first, everything worked well - I published a Codeunit with one Method that returned a text.

Yesterday I continued with "consuming" pages in VS2008 and I always got an InvalidOperationException: Path property must be set before calling the Send method. Well, I thought I would maybe misunderstand the Methods that were provided by the page and I went back to my origina lCodeunit-Webservice excample. Unfortunately now I also get the same error as soon as I call the ShowData method that worked before.

My source code looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            testWS.TestWebService testWebservice = new testWS.TestWebService();
            testWebservice.UseDefaultCredentials = true;
            Console.WriteLine(testWebservice.ShowData("bla"));
                   
        }
    }
}


whereas testWS is my WebReference to that published Codeunit and ShowData of course the NAV-function.

I have not changed anything intentionally on the Marketing Demo. I already rebooted the machine, I restarted the Web-Service and republished the Codeunit in NAV - nothing helped.

Maybe someone has any idea?!

Thanks & regards
Jut

Comments

  • JutJut Member Posts: 72
    Hmmm, I found out that I can solve that exception if I add the following line:

    testWebservice.Url = "http://localhost:7047/DynamicsNAV/ws/Codeunit/TestWebService";

    Now I unfortunately get the following exception:

    Microsoft.Dynamics.Nav.Types.Exceptions.NavNCLInvalidCompanyNameException: The supplied company name is not valid.

    I do not understand where a company name is supplied. My NAV function only returns a string and has a string as input.

    Do I forget something or is it just a little bit buggy?
  • JutJut Member Posts: 72
    Hmmm, I had renamed the Company in NAV to Cronus when I was experimenting with LINQ. Now I renamed it back to CRONUS Internation Ltd. to exclude this is a source of error.

    Is it possible that this error is still related to the fact that I temporarily had another company-name? The exception-description kind of looks alike. In fact I ask myself without finding an answer where in a Webservice is defined which Company the information that is retrieved by the webservice-method comes from? I saw that the "Web Service"-Table has DataperCompany=No, so this cannot be place where this information comes from.
  • JutJut Member Posts: 72
    It is again me, sorry for my monologue...;)

    Of course it was no bug in the system but my own error.

    When I added the web-reference I paid no attentation to the exact location.

    When I replaced http://localhost:7047/DynamicsNAV/ws/Co ... WebService by http://localhost:7047/DynamicsNAV/ws/CR ... WebService everything works fine. That might also answer my question where the company is defined. It is just defined in the url of the Webservice...that was easy...:)
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    It looks like you made it through.

    So I guess what happened is that you added a WebService reference when you had the old company name and after renaming the company back to CRONUS International... - you got the path property error.

    You can add the URL in code - but if you change the property on your web service reference - it actually generates a key in the app.config file - which can be changed when installing the module (typically you don't want URL's in source code):
    <applicationSettings>
            <CustomerTemplate.Properties.Settings>
                <setting name="CustomerTemplate_CustomerRef_Customer_Service"
                    serializeAs="String">
                    <value>http://localhost:7047/DynamicsNAV/WS/CRONUS_International_Ltd/Page/Customer</value>
                </setting>
            </CustomerTemplate.Properties.Settings>
        </applicationSettings>
    
    Another thing to notice with WebService References is the system webservice:

    http://localhost:7047/DynamicsNAV/WS/SystemService

    which does NOT require a company name - and it contains a function to return the possible companies.
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • ara3nara3n Member Posts: 9,256
    Now if only everybody wrote monologue as they were working, people would just use search in mibuso and find how a person solved every problem they run into.
    Ahmed Rashed Amini
    Independent Consultant/Developer


    blog: https://dynamicsuser.net/nav/b/ara3n
  • JutJut Member Posts: 72
    Freddy thank you for your interesting response.

    I continued working on my small project and I am again stuck a little bit. I am not sure if this is worth another new subject...

    I just tried to consume the NAV-Services in a Silverlight 2.0 application. Well, first I created my own small WCF-Service in the same project and it worked fine to consume it in my silverlight app. The next step was to consume a NAV-Page. This attempt already stopped when I tried to add a web reference to my NAV-Webservice - the Advanced Button in Add Service Reference just does not exist.

    Is there another way to use a NAV-Webservice in Silverlight (e.g. to wrap inside of another WFC-Service) or am I understanding something totally wrong?

    Thank you very much in advance!

    Regards,
    Jut
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    It is possible to connect to WSE 3.0 services from WCF directly, but it isn't as easy as using the Web Reference in VS and I haven't tried it myself, I probably will try this at some point in the future (for the fun of it) - but for now, I cannot help you.
    I will however ask around to see if anybody have tried this.

    No promises given, good luck. :?
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    I tested a little, created a Service Reference to my HTTP Web Service, changed the app.config manually to the following:
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <bindings>
          <basicHttpBinding>
            <binding name="Customer_Binding">
              <security mode="TransportCredentialOnly">
                <transport clientCredentialType="Windows" />
              </security>
            </binding>
          </basicHttpBinding>
        </bindings>
        <behaviors>
          <endpointBehaviors>
            <behavior name="allowDelegation">
              <clientCredentials>
                <windows allowedImpersonationLevel="Delegation"
                         allowNtlm="true"/>
              </clientCredentials>
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <client>
          <endpoint address="http://localhost:7047/DynamicsNAV/WS/CRONUS_International_Ltd/Page/Customer"
                    binding="basicHttpBinding"
                    bindingConfiguration="Customer_Binding"
                    behaviorConfiguration="allowDelegation"
                    contract="ServiceReference1.Customer_Port"
                    name="Customer_Port" />
        </client>
      </system.serviceModel>
    </configuration>
    
    and then the following code works:
    Customer_PortClient service = new Customer_PortClient();
    Customer_Filter filter = new Customer_Filter();
    filter.Field = Customer_Fields.No;
    filter.Criteria = "=10000";
    Customer[] customers = service.ReadMultiple(new Customer_Filter[] {filter}, "", 10);
    
    Good luck!
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • JutJut Member Posts: 72
    I tried this but I had no luck.

    The problem is that when I create a Silverlight ASP.NET Web-Application, I can add a Service-Reference to my NAV Page but when I try to consume I get the following warning and cannot access to any of the Webservice-Methods:

    Warning 1 Could not locate cross-domain policy at 'nav-srv-01': Web services might not be accessible at runtime by your Silverlight application. For more details please contact the web server administrator or press F1 after selecting this warning 0 0

    I understand that a Webservice-Host needs to publish such a clientaccesspolicy.xml but I do not know if I have a chance to include this into my NAV-Webservice. Do you have some additional information?

    Regards,
    Jut
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    The ClientAccessPolicy is for WCF - not WSE 3.0 (as far as I know)
    What is your setup? Sounds like you are not on the same domain as the WebService listener?
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • JutJut Member Posts: 72
    what setup do you mean`?

    My silverlight-web-app only has a web.config that I have not changed yet. Is this the place where I should put the source code that you mentioned to add to the app.config?

    Regards,
    Jut
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    Setup:
    Are you running the service tier on the same box as the webapp?
    what about the SQL Server?

    app.config:
    When you create the service reference - VS writes a lot of "stuff" regarding this reference in a config file (in my case app.config) - it might be web.config - you need to find that and change it to what I wrote.
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • JutJut Member Posts: 72
    This works all fine now but in order to use silverlight I have to use the async-methods that are also provided by NAV.

    Do you know if some documentation on this exist?

    My scenario works on the Marketing Beta Image and the silverlight-app has a service reference to
    http://localhost:7047/DynamicsNAV/WS/CR ... ge/Contact



    My Page.xaml.cs that is used for retrieving the data of my silverlight-app has the following source:
    public partial class Page : UserControl
        {
            public Contact[] cont1 { get; set; }
    
            public Page()
            {
                Contact_PortClient service = new Contact_PortClient();
                Contact_Filter filter = new Contact_Filter();
                filter.Field = Contact_Fields.No;
                filter.Criteria = "CT000008..CT000022";
                service.ReadMultipleAsync(new Contact_Filter[] { filter }, "", 2000);
                service.ReadMultipleCompleted += new EventHandler<ReadMultipleCompletedEventArgs>(service_ReadMultipleCompleted);
            }
    
            void service_ReadMultipleCompleted(object sender, ReadMultipleCompletedEventArgs e)
            {
                Contact[] cont1 = e.Result;
                myDataGrid2.ItemsSource = cont1;
            }
    

    When I run my application I get the following exception:
    An error occurred while trying to make a request to URI 'http://localhost:7047/DynamicsNAV/WS/CRONUS_International_Ltd/Page/Contact'. This could be due to attempting to access a service in a cross-domain way without a proper cross-domain policy in place, or a policy that is unsuitable for SOAP services. You may need to contact the owner of the service to publish a cross-domain policy file and to ensure it allows SOAP-related HTTP headers to be sent. Please see the inner exception for more details.

    I am not sure why this happens as the service and the app should work on the same domain. Is it possible to modify the *.config of the host of the NAV service?

    Regards,
    Jut
  • JutJut Member Posts: 72
    I continued working on that exception and it seems that the clientaccesspolicy.xml is the problem.

    In fact I copied this into the root-directory of the IIS (C:\Inetpub\wwwroot). I installed a Snifer-Tool (Web Developer Helper) and analyzed the calls that take place before the exeception is raised.

    It might be interesting to notice that the last calls are attempts to read the two policy-files from http://localhost:7047/clientaccesspolicy and http://localhost:7047/crossdomain.xml. These attempts fail with 400-Errors.

    I think the port might be interesting to notice. This is the port # of the NAV Middle Tier Server, not the Port of my Website what seems strange to me. I tried to change the Port of my Website from dynamic to static and to 7047 but then I cannot view the related TestPage because of the following error:

    Microsoft Visual Studio
    Unable to launch the ASP.NET Development Server. Port '7047' is in use.
    OK

    Is it maybe really necessary the copy the two xml-files to another directory or am I absolutely on the wrong track?

    Regards,
    Jut
  • JutJut Member Posts: 72
    I am not sure if someone is interested but I in case someone is, a short explanation of my solution.

    Freddy gave me some good additional tips and I really could imagine that his solution works, I was not able to get my Silverlight-Application directly connected to the NAV Webservice. I tried my original idea to create an intermediary silverlight-enabled webservice directly on my website. The contract of this webservice for example looks like:
    [OperationContract]
        public List<MyTypes.Contact> GetContacts(string setFilter)
        {
            // Add your operation implementation here
            Contact_PortClient service = new Contact_PortClient();
            Contact_Filter filter = new Contact_Filter();
            filter.Field = Contact_Fields.No;
            filter.Criteria = setFilter;
            Contact[] contacts = service.ReadMultiple(new Contact_Filter[] { filter }, "", 2);
            MyTypes.Contact cont = new MyTypes.Contact();
            List<MyTypes.Contact> conts = new List<MyTypes.Contact>();
    
            foreach (Contact navContact in contacts)
                {
                    cont.Address = navContact.Address;
                    conts.Add(cont);
                }  
    
            return conts;
        }
    

    This self-created webservice can then be called in my silverlight-application without any problem. The disadvantage of this solution is of course the need to duplicate the contract of the NAV-Webservices - in fact it would be very exhausting to copy for example the whole Contact-Page Contract i.e. all available fields. On the other hand in terms of contract-based programming it might be a good idea to choose the field that need to be exposed up front.

    Regards,
    Jut
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    Thanks for your post

    I just played a little around with Silverlight and Service Connections myself - and I think I know why you have to do this.
    The Silverlight control is running in context of the browser - and I don't think it supports to take the users credentials and use that towards a service.
    NAV Web Services requires authentication and the options supported by the NAV web services are not supported in the Silverlight control.
    So as you found out - you will need to have a proxy service (which then connects to NAV WebServices) - which actually is in line with what we recommend - never expose any webservices directly to the internet (which you would require if your silverlight control was to work for people not authenticated to the network).

    I would think that you could re-expose the types from the NAV WebService to avoid your doublework like
    public Customer GetCustomer()
            {
                Customer_Service service = new Customer_Service();
                service.UseDefaultCredentials = true;
    
                Customer_Filter filter = new Customer_Filter();
                filter.Field = Customer_Fields.No;
                filter.Criteria = "=10000";
    
                return service.ReadMultiple(new Customer_Filter[] { filter }, null, 0)[0];
            }
    
    but then your proxy contract will break if somebody customizes the Page in NAV.

    So I actually think your approach is the right choice) - expose the stuff you need through your proxy service is the same route I would take.
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • genericgeneric Member Posts: 511
    If you run your website on Linux php that consumed a nav webservice, would you run into any authenication issues?
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    I have never tried it - but I would guess that you could create a special windows user for WebServices connection from your PHP application, and then use specific credentials when connecting.
    The credentials for this user will now be in clear text in the PHP app - so you need to setup A/D restrictions on that user (no logins and stuff).
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • rossbrossb Member Posts: 3
    Regarding the initial post, I am using the demo, and i too get the following error message when trying to consume web services (and also in the application event log after starting the Business Web Services service): "The supplied company name is not valid."

    I can view services and add web references using only the non-company specific urls.

    The company name I would want to access is CRONUS USA, Inc. Neither http://tucvm07:7047/DynamicsNAV/WS/CRONUS_USA_Inc./Codeunit/<service name> nor http://tucvm07:7047/DynamicsNAV/WS/CRONUS_USA_Inc/Codeunit/<service name> work.

    Can anyone offer guidance? Nothing posted so far has seemed to work.

    Thanks,

    Ross
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    CRONUS_USA_x002C__Inc

    You should be able to enumerate the companies by calling the SystemService's Companies.
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • rossbrossb Member Posts: 3
    I tried that before posting and still got the invalid company notice. However, i tried different code after posting and it worked. I do not have the first sample code, so not sure what the difference is.

    Here is the code that helped me view the companies:

    // Create instance of service and setting credentials
    SystemService.SystemService service = new SystemService.SystemService();
    service.UseDefaultCredentials = true;
    // Set the service URL
    service.Url = "http://tucvm07:7047/DynamicsNAV/WS/SystemService";

    // Load all companies into an array
    string[] strarray = service.Companies();

    // Run through and print all companies
    foreach (string str in strarray)
    {
    MessageBox.Show(str);
    }

    CRONUS_USA_x002C__Inc works fine for consuming the web service, and after running the SystemService, the errors in the application log entries stopped.

    Thanks,

    Ross
  • freddy.dkfreddy.dk Member, Microsoft Employee Posts: 360
    Thanks for posting the code.

    The tricky thing about the CRONUS USA company name is that there are 2 underscores - I have seen a lot of people type it in and only type one.
    Also - it is case sensitive.
    Freddy Kristiansen
    Group Program Manager, Client
    Microsoft Dynamics NAV
    http://blogs.msdn.com/freddyk

    The information in this post is provided "AS IS" with no warranties, and confers no rights. This post does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion.
  • rossbrossb Member Posts: 3
    Yeah, I noticed that today, after a few attempts at thinking there was only one. :D
  • absolutelyfreewebabsolutelyfreeweb Member Posts: 104
    back to the original question, I should add something even though this is an old thread:

    If you are certain your company name is correct, the problem is most certainly the spaces in your company name. you can verify this with just the web browser and going to http://localhost:7047/DynamicsNAV/WS/company name/services with your browser. (replace company name) Try with company names without space.

    to remedy, try running the "system service" to see the company names the web services service expects. the system service is the only service not requiring a company. you can also try replacing spaces with underscore, or %20, depending on how nav is set to handle spaces in sql.
Sign In or Register to comment.