Can Dynamics NAV warehouse picks be updated via web service? - c#

I am building a C# console application that interacts with a Dynamics NAV web service in order to modify warehouse picks in NAV. Retrieving the pick lists and the associated items works perfectly, however, when I try to update a picking list I get HTTP Error 401: Unauthorized. The curious thing about that is that my user has super-permissions in NAV and should, therefore, be able to do anything I want.
The pick lists are published as a Page via a SOAP web service.
The only thing that I can think of that would sort of make sense, is if you simply couldn't modify pick lists via a web service. Does anyone have some info on that?
var service = new PickList_Service();
var credential = new NetworkCredential("MYDOMAIN\USER","PASSWORD");
service.Credentials = credential;
var list = service.Read("LIST IDENTIFIER");
list.AssignedUserID = "SOME USER";
service.Update(ref list); //<-- this is where the exception with the HTTP error is thrown

Not sure why you get unauthorized error, but if the goal is to modify the pick list and you can retrieve the data than why don't you just create a NAV codeunit with functions to modify pick list and publish it as a webservice.
Than it you would only require to call the mentioned codeunits method and pass there parameters retrieved from a part that already works (key or filters).

Related

How to retrieve a payment method on the client side?

We are running an App with a Angular/Typescript frontend and a .NET backend, using Stripe Elements and Stripe.NET respectively.
We are currently using the "Sources" API.
The frontend can create sources, the backend saves them to our specific users. When you open the frontend again, the backend sends a list of source ids. The frontend then collects the data it needs to display those sources directly from Stripe so the user can pick one of his saved sources to pay and does not have to enter all the data again.
Enter the Payment Method / Payment Intend API.
Due to EU regulations Stripe has a new API that requires us to create cards no longer as "source" but as a "PaymentMethod". So I implemented that in the backend, opened the frontend in my IDE, updated the #types/stripe-v3 package and found the new payment intent API.
The only thing missing: I cannot figure out how the frontend is to access the payment method data, once created. I can create it. Send it to the backend. The backend can retrieve it. Send back the ID to the frontend... and now what? How to display the payment methods available?
I had expected a stripe.retrievePaymentMethod() as there is a stripe.retrieveSource(). But no such luck.
The only option I currently see to present the user with a list of existing payment methods is getting this info on the backend and piping it all, class by class, property by property to the client. Basically copying every single data class stripe has into our own backend REST definition. That cannot be right.
What am I missing? Why is there no stripe.retrievePaymentMethod() on the frontend? Did I not understand some fundamental facts about what those APIs should do?
After contacting Stripe directly, it was confirmed that that's just the way it is:
I think it's just an oversight that we didn't add one.
There are similar functions in the mobile SDK so I don't see why we shouldn't have it
There are no immediate plans to add the functionality back in in the very near future,
so as a workaround, I will tunnel all the data through our backend(s).
If I understand as well, I think your problem is following and the sequence of that. I hope this helps you.
I have implemented a payment gateway like ccAvenue with DotNet and angular, in my case, I send the data to the server, and from the server, I tried to redirect to the payment gateway, but APIs return some result, and the result can not be redirected.
So I created a web-form with implementation, I redirected my app to web-forms page and from there I called the ccAvenue page, and in the response URL, I send the response page of webforms only and after saving the response I redirected to my angular app.
Here is workaround if you want to process 3Dsecure cards and still support other methods like SEPA.
You could attach both, confirmed PaymentIntent (payment method) or Source to the Customer object.
On your frontend you could implement both (StripeElements with client secret for 3Dsecure cards) and IBAN element for SEPA.
I could provide my code example how I save payment intent to the customer. It's in PHP, but for other languages logic should be the same.
Assuming that our client already confirmed PaymentIntent and we have it's id:
$intent = \Stripe\PaymentIntent::retrieve($stripe_intent_id);
$payment_method = \Stripe\PaymentMethod::retrieve($intent->payment_method);
$stripe_customer = Stripe\Customer::create([
'payment_method' => $intent->payment_method,
]);
In case you've already created Customer object before you could use attach method:
$payment_method->attach(['customer' => 'cus_FTkGe4lv5LfyI0']);
Then you'll be able to charge using Customer object PaymentMethod or Source;
I didn't try to attach both methods to the same customer object (we only allow customer to have one payment option at the same time), but it should work. Let me know if it works for you.

Handling credentials when accessing SharePoint data from .Net application

I am trying to access some SharePoint lists from a .Net (C#) web application. I googled the topic and it seemed the consensus was to use WCF Data Service (steps outlined below). After I get the data, I display it in a jQuery datatable, using Ajax web service call to grab the data.
Firt step was to run DataSvcUtil.exe to create a DataService.cs file that contains the client data service classes that are needed to access a data service from a .NET Framework client application. Then added references to Microsoft.Data.OData.dll and Microsoft.Data.Services.Client.dll.
I created a web service API (below). Run locally, from within VS 2017, or from IIS on application server, I get all the data, albeit in 80 seconds (way too long for 16,000 records). However when I ran this from a browser, I got status code 500 error and found out it was due to credential issue.
I was setting credentials to CredentialCache.DefaultCrdentilas (later changed to DefaultNetworkCredentials) but had to use NetworkCrdentials(UserID, pwd, domain).
[WebMethod]
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]
public string GetCompletedAssessments()
{
SPService_DataContext dc = new SPService_DataContext(new Uri("http://my_sp_site_.com/sites/nvx/SPService/_vti_bin/listdata.svc/"));
dc.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Had to change the above to this to get it to work
dc.Credentials = new System.Net.NetworkCredential(MyUserID, MyPassword, DomainName);
var source = dc.CompletedAssessments;
string JSONresult = JsonConvert.SerializeObject(source);
return JSONresult;
}
However, I was just testing it using my credentials which is not feasible. Is there anything I can do using the method of accessing data I am using, or should I use some other way of accessing the data that does not require providing credentials?
Application is on a server in same domain as the server SharePoint in on but in a different location.
If you want the application to read the data, you must supply the credentials.
You could try to use REST or JSOM to fetch the data from the client. That way the users credentials are used and the result will be security trimmed.
REST example: http://my_sp_site_.com/sites/nvx/SPService/_api/web/lists/GetByTitle('Pages')/items
If you add an Accept header with application/json;odata=verbose, the result is in JSON. Otherwise its in XML.
SharePoint REST documentation: https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/working-with-lists-and-list-items-with-rest

C# Web API - Security for some of the GET requests

On an existing host I've added Web API Models & Controllers. I've added the following four:
Products
Orders
Categories
Users
When someone accesses the localhost:port\api\products, it returns all the products in JSON format.
The Create, Update and Delete statements are completely disabled, so we are only able to use GET-requests on the API (so either \api\products for a list of all products or api\products\# for a single products with id #).
Because the other CRUD's aren't used, there isn't a lot of security that should be added to the Web API, except for one thing: The Users
These will also return emails and such, which would be better to keep private and unreadable without the proper authorization (without entire log-in pages, but a way to authenticate yourself when accessing the Web API in for example Android HttpGetRequests).
So, the question: How should I add authorization for only the UsersController accessed by the Web API.
And, how can I encrypt the JSON in C# and decrypt it in Android again. If this second part is too big to answer I'll make a new question later on, my main focus is the low-end [<- without log-in pages, so built in into the GET-request] authorization of the Web API's GET-request for Users.
Edit 1: I did found this link where a new project is made with Authorization Changed to Individual Users. I also see that the user is registered and then logged in with POST and GET requests.
The following questions came into mind when reading through this link:
How to change the Web API's Authorization to Individual Users on an existing project?
Our authorization is done through OAuth (mainly Google-account) with our work e-mail address. I guess it's not possible / easy to authorize in the same way as in the link with a Google-account on Web API GET-requests.
Edit 2: After using the first link provided by Vladimir Gondarev I've added the [Authorize] to both the Get methods in the UsersController. In my project everything else was already used before, like a class that uses the AuthorizeAttribute, so just adding the [Authorize] was already enough for the first step. Now in the browser I get an unauthorized (JSON) back when I'm not logged in, which is good.
The next step would be to add the OAuth-authorization to the Android app, but that is an entire new problem / question that I will look into first before asking a new stackoverflow-question.
The simplest solution would be "Basic Authentification". In order to to implement it you have to derive from AuthorizeAttribute and then apply it to a method or a controller.
Here you find further info:
What is basic Authentification:
http://www.asp.net/web-api/overview/security/basic-authentication
Implementation:
ASP.net Web API RESTful web service + Basic authentication
You don't have to encrypt anything as long as you use HTTPS transport.

Online CRM REST Service - Struck with an issue

This is a simple task, but i am wasting more than a day. Thats why coming to you. Please help me to get out of the issue.
My requirement is very simple, i have an ASP.NET project. And i have an Entity in Online CRM
Entity Name: "Employee" and Fields are "Name, Age, Gender"
I cann't add CRM Dlls in my asp.net project. So i must use REST Service.
I have added service reference https://myoffice.crm5.dynamics.com/xrmservices/2011/organization.svc?wsdl
This is the code i am using
OrganizationServiceClient orgClient = new OrganizationServiceClient();
orgClient.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential("admin#something.com", "mypassword");
Entity myContact = new Entity();
myContact.LogicalName = "Employee"; //Is it right? i must provide it here right.
ConsoleApplication1.ServiceReference2.AttributeCollection myAttColl = new ConsoleApplication1.ServiceReference2.AttributeCollection();
myAttColl.Add(new KeyValuePair<string, object>("Name","Emp1"));
myAttColl.Add(new KeyValuePair<string, object>("Age", "26"));
myAttColl.Add(new KeyValuePair<string, object>("Gender", "Male"));
myContact.Attributes = myAttColl;
try
{
orgClient.Create(myContact);
}
catch (Exception ex)
{
}
I am getting "An error occurred when verifying security for the message" error when it run orgClient.Create(myContact).
No matter what i did so far. This is my requirement, a very simple adding entry to my custom entity into Online CRM using REST Service. I am going to run my webapplication in a separate domain called http://xyz.com. From here, i need to add the entries into Online CRM.
Any help?
It could seems strange but the reason is that the clock on the server and on the client are certainly not synchronized.
All you have to do is check that :
The client clock is synched with the server clock.
Both client and server are coordinated on the day time saving settings
Regards,
Kévin
Sources : here and here
The REST service is not exposed for external applications, it is for internal applications only. You may be able to get around this in an on premise deployment but in CRM Online there is no workaround that I am aware of. You are much better off if you add the CRM assemblies and do this in C#. Also, with the REST service you are severely limited to CRUD operations and you can't perform things like assign or change state. In my opinion the SOAP service is superior, but it still cannot be called from an external web application.
See the note that reads the following at this link - Data Access Using JavaScript
Note
It is not possible for an external application to use these web services because authentication is provided by Microsoft Dynamics CRM.

I am trying to consume a PHP SOAP service from C# and create a class wrapper in VS 2010

I've been tasked with creating a class wrapper for a SOAP service, the idea is that you'll be able to treat it as a regular class. The main reason for this is that the WDSL for the SOAP service contains only one method and it's got 5 parameters and it's only kind of OO so you'd have to know all the method calls really well and it's a bit hard to remember them all.
OK, so I've tried adding a web reference, now web references can now be added as service references in VS 2010. You click add service reference advanced etc and it puts in a service reference. Great. Unfortunately if I try and access this from a class I can't.
I can build a console app and put code in the main procedure and access the method of the SOAP service fine but when I add a reference to a class library the intellisense won't allow me to select anything. I'd instantiate an instance like so:
SOAPService.webServiceService ws = new SOAPService.webserviceService();
ws.
and then the intellisense refuses to kick in. If I do the same in a web project or a console app then I can access it fine. I've added the namespace I've done all kinds of things. Also, I can add a web reference and get a DISCO file whenever I create a web project.
OK, also while I'm on the subject I also need to pass credentials to the web service in PHP.
The problem is that in the past I'd create some .net system credentials and add these and it would usually pass through if I was connecting to another .net service.
How should I be sending them to a PHP web service? I always get either invalid username/password combo errors or envelope malformatted error types
Thanks
Mr. B
So the intellisense is not working, but if you add the method in and try to use it does it work, or produce an error?
With regard to diagnosing authentication issues try using fiddler to view the SOAP messages that are being sent, and to view the reply. Do you have some other software that connects and authenticates to that service? Use fiddler to look at the SOAP messages and compare them to see if the header is different etc.
I'd normally do it like this,
using (Service service = new Service())
{
service.ClientCredentials.Windows.ClientCredential.Domain = "domain";
service.ClientCredentials.Windows.ClientCredential.Password = "password";
service.ClientCredentials.Windows.ClientCredential.UserName = "username";
}
Also with regard to the service working or not in general use fiddler if you have any problems, you can see the SOAP messages and it often gives you a clearer message.
I know in IIS you can turn on failed request handling that also gives you an insight from what is going on at the server end, perhaps you have some form of logging too for your php service?

Categories

Resources