question

DavidAnderson-4633 avatar image
0 Votes"
DavidAnderson-4633 asked YijingSun-MSFT commented

How do you reference code in ASP.NET Web Application Packages folder?

I have used the NuGet Package Manager in Visual Studio 2019 to install PayPal's Checkout SDK (PaypalCheckoutSdk) in a new ASP.NET Web Application project. PaypalCheckoutSdk was stored by default in the Packages folder of this project, as shown below. As instructed in Set up PayPal SDK, I also copied PayPal's .NET code for "setting up the environment" and pasted it into a new file I chose to call PayPalAPI.cs, which was stored in that same folder.

…\packages\PayPalCheckoutSdk.1.0.4\lib\netstandard2.0\

A copy of PayPalAPI.cs is shown at the end of this post. Note that it defines a public class of PayPalClient. With the guidance at Create PayPal Order, I then used VS 2019 to create a new PayPalOrder.cs page in the root of my .NET project containing PayPal's sample code for creating an order (as shown below).

My problem is that VS 2019 highlights several errors in PayPalOrder.cs.

  • Line 30: ­ The name 'PayPalClient' does not exist in the current context

  • Line 59: ­ 'OrderRequest' does not contain a definition for 'Intent'

  • Line 75: ­ 'PurchaseUnitRequest' does not contain a definition for 'Amount'

  • Line 79: ­ 'AmountWithBreakdown' does not contain a definition for 'Breakdown'

  • Line 147: ­ 'PurchaseUnitRequest' does not contain a definition for 'Shipping'

  • Line 147: ­ The type or namespace name 'ShippingDetails' could not be found

Interestingly, I found that a copy of PayPalOrder.cs placed in the same folder as the SDK itself did not display any of these errors. However, that is not a practical location for my code, as the Packages folder is not normally accessible via Visual Studio’s Solution Explorer.

I would be very grateful for any guidance on how to fix these errors, which probably all result from the inability of PayPalOrder.cs to reference the PayPalClient class defined in PayPalAPI.cs.


PayPalOrder.cs

 using System;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 //1. Import the PayPal SDK client that was created in `Set up Server-Side SDK`.
 using PayPalCheckoutSdk.Core;
 using PayPalCheckoutSdk.Orders;
    
 // Added by me to eliminate an Http error
 using PayPalHttp;
    
 namespace Samples.CaptureIntentExamples
 {
     public class CreateOrderSample
     {
    
         //2. Set up your server to receive a call from the client
         /*
           Method to create order
    
           @param debug true = print response data
           @return HttpResponse<Order> response received from API
           @throws IOException Exceptions from API if any
         */
         public async static Task<HttpResponse> CreateOrder(bool debug = false)
         {
             var request = new OrdersCreateRequest();
             request.Prefer("return=representation");
             request.RequestBody(BuildRequestBody());
             //3. Call PayPal to set up a transaction
             var response = await PayPalClient.client().Execute(request);
    
             if (debug)
             {
                 var result = response.Result<Order>();
                 Console.WriteLine("Status: {0}", result.Status);
                 Console.WriteLine("Order Id: {0}", result.Id);
                 Console.WriteLine("Intent: {0}", result.Intent);
                 Console.WriteLine("Links:");
                 foreach (LinkDescription link in result.Links)
                 {
                     Console.WriteLine("\t{0}: {1}\tCall Type: {2}", link.Rel, link.Href, link.Method);
                 }
                 AmountWithBreakdown amount = result.PurchaseUnits[0].Amount;
                 Console.WriteLine("Total Amount: {0} {1}", amount.CurrencyCode, amount.Value);
             }
    
             return response;
         }
    
         /*
           Method to generate sample create order body with CAPTURE intent
    
           @return OrderRequest with created order request
          */
         private static OrderRequest BuildRequestBody()
         {
             OrderRequest orderRequest = new OrderRequest()
             {
                 Intent = "CAPTURE",
    
                 ApplicationContext = new ApplicationContext
                 {
                     BrandName = "EXAMPLE INC",
                     LandingPage = "BILLING",
                     UserAction = "CONTINUE",
                     ShippingPreference = "SET_PROVIDED_ADDRESS"
                 },
                 PurchaseUnits = new List<PurchaseUnitRequest>
         {
           new PurchaseUnitRequest{
             ReferenceId =  "PUHF",
             Description = "Sporting Goods",
             CustomId = "CUST-HighFashions",
             SoftDescriptor = "HighFashions",
             Amount = new AmountWithBreakdown
             {
               CurrencyCode = "USD",
               Value = "230.00",
               Breakdown = new AmountBreakdown
               {
                 ItemTotal = new Money
                 {
                   CurrencyCode = "USD",
                   Value = "180.00"
                 },
                 Shipping = new Money
                 {
                   CurrencyCode = "USD",
                   Value = "30.00"
                 },
                 Handling = new Money
                 {
                   CurrencyCode = "USD",
                   Value = "10.00"
                 },
                 TaxTotal = new Money
                 {
                   CurrencyCode = "USD",
                   Value = "20.00"
                 },
                 ShippingDiscount = new Money
                 {
                   CurrencyCode = "USD",
                   Value = "10.00"
                 }
               }
             },
             Items = new List<Item>
             {
               new Item
               {
                 Name = "T-shirt",
                 Description = "Green XL",
                 Sku = "sku01",
                 UnitAmount = new Money
                 {
                   CurrencyCode = "USD",
                   Value = "90.00"
                 },
                 Tax = new Money
                 {
                   CurrencyCode = "USD",
                   Value = "10.00"
                 },
                 Quantity = "1",
                 Category = "PHYSICAL_GOODS"
               },
               new Item
               {
                 Name = "Shoes",
                 Description = "Running, Size 10.5",
                 Sku = "sku02",
                 UnitAmount = new Money
                 {
                   CurrencyCode = "USD",
                   Value = "45.00"
                 },
                 Tax = new Money
                 {
                   CurrencyCode = "USD",
                   Value = "5.00"
                 },
                 Quantity = "2",
                 Category = "PHYSICAL_GOODS"
               }
             },
             Shipping = new ShippingDetails
             {
               Name = new Name
               {
                 FullName = "John Doe"
               },
               AddressPortable = new AddressPortable
               {
                 AddressLine1 = "123 Townsend St",
                 AddressLine2 = "Floor 6",
                 AdminArea2 = "San Francisco",
                 AdminArea1 = "CA",
                 PostalCode = "94107",
                 CountryCode = "US"
               }
             }
           }
         }
             };
    
             return orderRequest;
         }
    
         /*
            This is the driver function that invokes the createOrder function
            to create a sample order.
         */
         static void Main(string[] args)
         {
             CreateOrder(true).Wait();
         }
     }
 }

PayPalAPI.cs

 using System;
 using PayPalCheckoutSdk.Core;
 using PayPalHttp;
    
 using System.IO;
 using System.Text;
 using System.Runtime.Serialization.Json;
    
 namespace Samples
 {
     public class PayPalClient
     {
         /**
             Set up PayPal environment with sandbox credentials.
             In production, use LiveEnvironment.
          */
         public static PayPalEnvironment environment()
         {
             return new SandboxEnvironment("PAYPAL-SANDBOX-CLIENT-ID","PAYPAL-SANDBOX-CLIENT-SECRET");
         }
    
         /**
             Returns PayPalHttpClient instance to invoke PayPal APIs.
          */
         public static HttpClient client()
         {
             return new PayPalHttpClient(environment());
         }
    
         public static HttpClient client(string refreshToken)
         {
             return new PayPalHttpClient(environment(), refreshToken);
         }
    
         /**
             Use this method to serialize Object to a JSON string.
         */
         public static String ObjectToJSONString(Object serializableObject)
         {
             MemoryStream memoryStream = new MemoryStream();
             var writer = JsonReaderWriterFactory.CreateJsonWriter(
                         memoryStream, Encoding.UTF8, true, true, "  ");
             DataContractJsonSerializer ser = new DataContractJsonSerializer(serializableObject.GetType(), new DataContractJsonSerializerSettings{UseSimpleDictionaryFormat = true});
             ser.WriteObject(writer, serializableObject);
             memoryStream.Position = 0;
             StreamReader sr = new StreamReader(memoryStream);
             return sr.ReadToEnd();
         }
     }
 }
















dotnet-standarddotnet-aspnet-webforms
· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Your post is a little confusing but the PayPalClient class should exist in a file within the web application project.

Take a closer look at the PayPalAPI.cs file, the PayPalClient class is within the "Samples" namespace. I would change the namespace, Samples, to your project's namespace. Whatever that namespace might be... Otherwise, include the Samples namespace (fully qualified name) to invoke the static method.

 var response = await Samples.PayPalClient.client().Execute(request);

See the following reference documentation which explains what a namespace is and how namespaces are used,

Declare namespaces to organize types
General Structure of a C# Program


0 Votes 0 ·

Hi Joe,
Using a fully qualified name of Samples.PayPalClient.client() didn't work. I had already tried changing namespaces but without any success. I can't now remember exactly what changes I tried so I've now given your suggestion a go.

The default namespace for my web app is MyTestCSharpWebApp2, so I changed the namespace in PayPalAPI.cs from Samples to MyTestCSharpWebApp2 and changed the namespace in PayPalOrder.cs from Samples.CaptureIntentExamples to MyTestCSharpWebApp2, but sadly this also didn't fix my problem.

When I switch to the Class View in VS 2019, the class list under MyTestCSharpWebApp2 does not include PayPalClient. It doesn't seem to have access to code located in the Packages folder I quoted.

0 Votes 0 ·

PayPal's instructions in Set up PayPal SDK clearly state that the code I have placed in PayPalAPI.cs should be located in the same directory as the SDK. On the assumption that this was an error and they really meant to say in the same ASP.NET project, I have tried moving PayPalAPI.cs into the root of my project.

That now locates PayPalClient in my project namespace and makes it available to PayPalOrder.cs. However, PayPalAPI.cs now generates the error: The name 'JsonReaderWriterFactory' does not exist in the current context. Why is that error occurring when PayPalAPI.cs contains 'using System.Runtime.Serialization.Json;'?


0 Votes 0 ·
YijingSun-MSFT avatar image YijingSun-MSFT DavidAnderson-4633 ·

Hi @DavidAnderson-4633 ,
What's your .net framework? In .NET 3.5,it is in System.ServiceModel.Web.dll.And you need to add System.ServiceModel.Web.dll. If your project is in .NET 4.0 and above, it is in System.Runtime.Serialization.dll.
Make sure you have added the correct DLL as a reference in your project and add using System.Runtime.Serialization.Json; to the top of your code file.

Best regards,
Yijing Sun

0 Votes 0 ·
Show more comments

1 Answer

DavidAnderson-4633 avatar image
0 Votes"
DavidAnderson-4633 answered YijingSun-MSFT commented

@AgaveJoe
PayPal's instructions in Set up PayPal SDK provide code for "setting up the environment", which they clearly state should be placed in the same directory as the SDK (which in my case means within the solution Packages folder). However, all attempts to access the PayPalClient class defined in that code have failed. I am now of the opinion that PayPal's advice is wrong and that this code should be located within the root of the project folder. There is then no problem in accessing the PayPalClient class.

I still have the other errors listed in my OP, but if I can't fix those I will raise a new question.


· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

which they clearly state should be placed in the same directory as the SDK

The packages folder is a local where NuGet keeps track of packages including package information and DLLs (built libraries). The actual SDK (DLL) is copied (installed) to your project's bin folder. Every DLL in the bin folder is available to the entire .NET project. A "using" statement at the top of a code file points to the namespace of a DLL located in the bin folder. This construct allows the code file to access members of the DLL without having to use a fully qualified name.

Your complaint is similar to a gardening project. You buy flower to plant in the garden but complain the flower instructions only explain how to care for the flower not how to build and maintain a garden.

0 Votes 0 ·

@AgaveJoe
As it happens, I understand much more about garden design than I do about the internal plumbing of ASP.NET! I'm all too aware of the gaps in my knowledge, which is why I'm posting questions here, in the hope that experts like you can help to plug those gaps :)

Your comment has made me notice for the first time that a fresh new Web Application like the one under discussion does not display a Bin folder in Solution Explorer. An older Web App of mine does have a Bin folder, which looks like it was created specifically to accommodate the needs of ASP.NET Identity.

EDIT: I've found the Bin folder. I'd forgotten that this is hidden unless you click the Show All Files button. Moving my PayPalAPI.cs file to the Bin folder works fine, though not any differently (as far as I can see) from when it was in the root of the project. Thanks for clarifying what PayPal really meant by referring to the "same directory as the SDK".

0 Votes 0 ·
AgaveJoe avatar image AgaveJoe DavidAnderson-4633 ·

I'm all too aware of the gaps in my knowledge, which is why I'm posting questions here, in the hope that experts like you can help to plug those gaps :)

the community is trying to fill the gaps but you find interesting ways to go off the rails.

I've found the Bin folder. I'd forgotten that this is hidden unless you click the Show All Files button. Moving my PayPalAPI.cs file to the Bin folder works fine, though not any differently (as far as I can see) from when it was in the root of the project. Thanks for clarifying what PayPal really meant by referring to the "same directory as the SDK".

Source code files like PayPalAPI.cs do not belong in the bin folder. PayPalAPI.cs belongs in a folder in the root project. A folder named "Services" is sound location for a PayPal client. The bin folder is a special folder and contains the results of compiling source files; DLLs. Once PayPalAPI.cs is compiled (built) it will exist in a DLL within the bin folder which is the same directory as the SDK.



0 Votes 0 ·
Show more comments