I would like to ask about shopify pagination version 2020-01
First request query:
URL: https://klevarange.myshopify.com/admin/api/2020-01/orders.json?fulfillment_status=unfulfilled&limit=250&financial_status=paid&created_at_min=2019-08-27T16:15:47-04:00
Return Header:
"<https://klevarange.myshopify.com/admin/api/2020-01/orders.json?limit=250&page_info=eyJmaW5hbmNpYWxfc3RhdHVzIjoicGFpZCIsImZ1bGZpbGxtZW50X3N0YXR1cyI6InVuZnVsZmlsbGVkIiwiY3JlYXRlZF9hdF9taW4iOiIyMDE5LTA4LTI3IDIwOjE1OjQ3IFVUQyIsImxhc3RfaWQiOjIxMDQ4NzIxNzM2NTIsImxhc3RfdmFsdWUiOiIyMDIwLTAyLTI3IDAwOjA5OjUyIiwiZGlyZWN0aW9uIjoibmV4dCJ9>; rel=\"next\""
2nd Request Query:
"https://klevarange.myshopify.com/admin/api/2020-01/orders.json?limit=250&page_info=eyJmaW5hbmNpYWxfc3RhdHVzIjoicGFpZCIsImZ1bGZpbGxtZW50X3N0YXR1cyI6InVuZnVsZmlsbGVkIiwiY3JlYXRlZF9hdF9taW4iOiIyMDE5LTA4LTI3IDIwOjE1OjQ3IFVUQyIsImxhc3RfaWQiOjIxMDQ4NzI1MzQxMDAsImxhc3RfdmFsdWUiOiIyMDIwLTAyLTI3IDAwOjEwOjA3IiwiZGlyZWN0aW9uIjoibmV4dCJ9>; rel=\"next\""
Result: Bad Request
What should I put in page_info? Do I need to include the rel=\"next\"" in the page_info?
Thank you.
Remove > from your page_info variable
var page_info = "eyJmaW5hbmNpYWxfc3RhdHVzIjoicGFpZCIsImZ1bGZpbGxtZW50X3N0YXR1cyI6InVuZnVsZmlsbGVkIiwiY3JlYXRlZF9hdF9taW4iOiIyMDE5LTA4LTI3IDIwOjE1OjQ3IFVUQyIsImxhc3RfaWQiOjIxMDQ4NzI1MzQxMDAsImxhc3RfdmFsdWUiOiIyMDIwLTAyLTI3IDAwOjEwOjA3IiwiZGlyZWN0aW9uIjoibmV4dCJ9"
and Make your request URL like below.
https://klevarange.myshopify.com/admin/api/2020-01/orders.json?limit=250&page_info={page_info}
Digging Deeper
You need to iterate your while loop until there is no Link Parameter in the response header and this parameter is not a static value it is the address of last object you get and saying next will give you next 250 objects.
you need to update your pageInfo parameter in every request with newly generated next reference ( pageInfo )
When you do not get this parameter that means there is no next or previous page .
Have a look in this below code...( written in php )
How to create pagination in shopify rest api using php
You should use only this part: https://klevarange.myshopify.com/admin/api/2020-01/orders.json?limit=250&page_info=eyJmaW5hbmNpYWxfc3RhdHVzIjoicGFpZCIsImZ1bGZpbGxtZW50X3N0YXR1cyI6InVuZnVsZmlsbGVkIiwiY3JlYXRlZF9hdF9taW4iOiIyMDE5LTA4LTI3IDIwOjE1OjQ3IFVUQyIsImxhc3RfaWQiOjIxMDQ4NzI1MzQxMDAsImxhc3RfdmFsdWUiOiIyMDIwLTAyLTI3IDAwOjEwOjA3IiwiZGlyZWN0aW9uIjoibmV4dCJ9 i.e. without rel="next"
In the 2nd and all next requests, you can only pass up to 3 query parameters:
page_info
limit
fields
So if you want to get results from the next page you need to extract page_info value from the first response headers.
The idea is that you can move only forward or backwards while requesting the results and you can get the link (page_info token) to the next (or previous) page only after retrieving the current page results.
Maybe in the last 2 years, Shopify has made some modifications to their API, then I use GetNextPageFilter method. This is my approach.
public async Task<IEnumerable<Product>> ProductsGetList(string shopUrl, string accessToken)
{
var products = new List<Product>();
var service = new ProductService(shopUrl, accessToken);
var filter = GetFilters(shopUrl);
var productList = await service.ListAsync(filter);
if (productList != null && productList.Items.Any())
{
products.AddRange(productList.Items);
bool hasMorePages = productList.HasNextPage;
if (hasMorePages)
{
do
{
var filterList = productList.GetNextPageFilter(filter.Limit, filter.Fields);
productList = await service.ListAsync(filterList);
if (productList != null && productList.Items.Any())
{
products.AddRange(productList.Items);
hasMorePages = productList.HasNextPage;
}
} while (hasMorePages);
}
}
return products;
}
private ProductListFilter GetFilters(string url)
{
ProductListFilter filters = new ProductListFilter();
string queryString = new System.Uri(url).Query;
var queryDictionary = System.Web.HttpUtility.ParseQueryString(queryString);
foreach (var parameter in queryDictionary)
{
var key = (string)parameter;
var value = queryDictionary.Get(key);
switch (key)
{
case "published_status":
filters.PublishedStatus = value;
break;
case "published_at_max":
filters.PublishedAtMax = DateTimeOffset.Parse(value);
break;
case "published_at_min":
filters.PublishedAtMin = DateTimeOffset.Parse(value);
break;
case "updated_at_max":
filters.UpdatedAtMax = DateTimeOffset.Parse(value);
break;
case "updated_at_min":
filters.UpdatedAtMin = DateTimeOffset.Parse(value);
break;
case "created_at_max":
filters.CreatedAtMax = DateTimeOffset.Parse(value);
break;
case "presentment_currencies":
filters.PresentmentCurrencies = value.Split(',').AsEnumerable();
break;
case "created_at_min":
filters.CreatedAtMin = DateTimeOffset.Parse(value);
break;
case "status":
filters.Status = value;
break;
case "product_type":
filters.ProductType = value;
break;
case "handle":
filters.Handle = value;
break;
case "vendor":
filters.Vendor = value;
break;
case "title":
filters.Title = value;
break;
case "since_id":
filters.SinceId = long.Parse(value);
break;
case "collection_id":
filters.CollectionId = long.Parse(value);
break;
case "ids":
filters.Ids = value.Split(',').AsEnumerable().Cast<long>();
break;
case "limit":
filters.Limit = int.Parse(value);
break;
}
}
return filters;
}
Where shopUrl is the entire URL (https://{apiKey}:{password}#{hostname}/admin/api/{version}/{resource}.json) and accessToken is the URL {password} atribute
I'm writing this simple code in html:-
<a id="{{L.ID}}" target="_blank" href="/Home/RedirectToMaterialView?MaterialTypeID={{L.MaterialTypeID}}&SearchListID={{L.SearchListID}}&Category={{L.Category}}" style="cursor:pointer">Open</a>
Now this goes to my HomeController and works perfect in my local machine, where I redirect it to some other actionlink. c# controller actionresult is like this:-
public ActionResult RedirectToMaterialView(string MaterialTypeID, string SearchListID, string Category)
{
if (!string.IsNullOrEmpty(SearchListID))
{
dbundle.MaterialFetchID = Convert.ToInt32(SearchListID);
dbundle.MaterialIndicator = Convert.ToInt32(MaterialTypeID);
dbundle.MaterialFor = Convert.ToString(Category);
string queryString = string.Empty;
TempData["DBundle"] = dbundle;
switch (dbundle.MaterialFor)
{
case "Class":
switch (dbundle.MaterialIndicator)
{
case 1:
TempData["ClassMaterialHeading"] = Constants.EBook;
break;
case 2:
TempData["ClassMaterialHeading"] = Constants.Notes;
break;
default:
TempData["ClassMaterialHeading"] = "";
break;
}
return RedirectToAction(Constants.ClassMaterial, new { id= dbundle.MaterialFetchID, MatFor =dbundle.MaterialFor});
case "Degree":
switch (dbundle.MaterialIndicator)
{
case 1:
TempData["DegreeMaterialHeading"] = Constants.EBook;
break;
case 2:
TempData["DegreeMaterialHeading"] = Constants.Notes;
break;
default:
TempData["DegreeMaterialHeading"] = "";
break;
}
return RedirectToAction(Constants.DegreeMaterial, new { id = dbundle.MaterialFetchID, MatFor = dbundle.MaterialFor });
default:
return RedirectToAction(Constants.School);
}
}
else
return RedirectToAction(Constants.Degree);
}
But when I run this code on server. It's redirecting to a blank page.
I don't know what's creating problem. Maybe I'm missing something in the link. But I can't figure out what's the problem on server which is not on my machine.
Help Appreciated.
I'm new to asp.net mvc & I'm trying to make a website where user can sort a table after login. When I build the project I get errors like, Does not contain a definition for 'OrderByDescending'/'OrderBy'/'ToList'. Here are my codes,
Controller
ViewBag.CodeSort = String.IsNullOrEmpty(sortOrder) ? "code_desc" : "";
var sortedOut = new MkistatVsUserLogin { mkistats = dsedb.mkistats.AsQueryable() }; //Error in this line
switch (sortOrder)
{
case "code_desc":
sortedOut = sortedOut.OrderByDescending(s => s.MKISTAT_CODE); //error in this line
break;
default:
sortedOut = sortedOut.OrderBy(s => s.MKISTAT_CODE); //error in this line
break;
}
return View(sortedOut.ToList()); //error in this line
Model
public class MkistatVsUserLogin
{
public IQueryable<mkistat> mkistats { get; set; }
public idx Idxs { get; set; }
}
How can I solve this problem? Need this help badly. Tnx.
Because the IQueryable is the mkistats, not the sortedOut!
ViewBag.CodeSort = String.IsNullOrEmpty(sortOrder) ? "code_desc" : "";
var sortedOut = new MkistatVsUserLogin { mkistats = dsedb.mkistats.AsQueryable() }; //Error in this line
switch (sortOrder)
{
case "code_desc":
sortedOut.mkistats = sortedOut.mkistats.OrderByDescending(s => s.MKISTAT_CODE); //error in this line
break;
default:
sortedOut.mkistats = sortedOut.mkistats.OrderBy(s => s.MKISTAT_CODE); //error in this line
break;
}
return View(sortedOut); //error in this line
And the switch is wrong, but I am not sure how to solve it. It should probably be
switch (ViewBag.CodeSort)
Note that as the code is written, the view will only receive a List<mkistat>, not a full MkistatVsUserLogin object.
OrderByDescending is an extension method inside of System.Linq.
Make sure you have the relevant using statemenet at the top of your class
using System.Linq;
Give code like this:
switch (args[0])
{
case "foo":
{
var operation = new FooOperation();
operation.Do();
break;
}
case "bar":
{
var operation = new BarOperation();
operation.Do();
break;
}
default: throw new Exception();
}
I want to pull the common parts out of the switch, like this:
IOperation operation;
switch (args[0])
{
case "foo":
{
operation = new FooOperation();
break;
}
case "bar":
{
operation = new BarOperation();
break;
}
default: throw new Exception();
}
operation.Do();
And I want to do it without typing - just ReSharper transformations. Is there a way to do that?
(For a complete program that is legal and compiles, see https://gist.github.com/JayBazuzi/2457e8389d338688a9ab and https://gist.github.com/JayBazuzi/798bdca40d59e095e83b)
I have an enumeration like (a,b,c,d).
public enum BeatSession
{
on_ended,
on_new,
on_hold,
on_paused,
on_accepted,
on_answered,
on_timed_out,
on_hanged_up,
on_initiated,
unknown
}
and a method to do a switch on the enumeration.
public static string GetStatusMessage(BeatSession status, string custom_message="")
{
string msg = "";
try
{
switch (status)
{
case BeatSession.on_answered:
// msg will be here
break;
case BeatSession.on_ended:
// msg will be here
break;
case BeatSession .on_hanged_up:
// msg will be here
break;
case BeatSession.on_hold:
// msg will be here
break;
case BeatSession.on_new:
break;
case BeatSession.on_paused:
// msg will be here
break;
case BeatSession.on_timed_out:
// msg will be here
break;
case BeatSession.on_accepted:
// msg will be here
break;
default:
msg = "Unknown";
break;
}
}
catch (Exception ex)
{
throw ex;
}
// Override message
if (!String.IsNullOrEmpty(custom_message))
{
msg = custom_message;
}
return msg;
}
Updated
However, every time I call my method GetStatusMessage(BeatSession.on_ended).
Even if I pass "on_ended" it goes to "on_answered".
I tried re-arranging "public enum BeatSession". When I passed "on_ended" it now goes to "on_accepted".
Screenshot
Notice the watch for session_status varriable.
I have some code where i do something like this
public enum Letters
{
A = 1,
B = 2,
...
}
public void someFunction(int value)
{
switch(value)
{
case (int)Letters.A: {/* Code */ break;}
case (int)Letters.B: {/* Code */ break;}
...
}
}
And it works, but i think what you are trying to do is send the enum and use it in the switch in the switch, maybe something like this will work
public void someFunction(Letters l)
{
switch(l)
{
case Letters.A: {/* Code */ break;}
case Letters.B: {/* Code */ break;}
...
}
}
Your current code shouldn't compile, following are the main problems.
First, the method definition contains a parameter enum status, you can't do that, It seems you need a parameter of type BeatSession, you should modify the function to:
public static string GetStatusMessage(BeatSession status, string custom_message="")
{
...
}
Next thing in your case statement, you are using enum.on_answered, this should be BeatSession.on_answered. So your complete function should be:
public static string GetStatusMessage(BeatSession status, string custom_message = "")
{
string msg = "";
try
{
switch (status)
{
case BeatSession.on_answered:
// msg will be here
break;
case BeatSession.on_ended:
// msg will be here
break;
case BeatSession.on_hanged_up:
// msg will be here
break;
case BeatSession.on_hold:
// msg will be here
break;
case BeatSession.on_new:
break;
case BeatSession.on_paused:
// msg will be here
break;
case BeatSession.on_timed_out:
// msg will be here
break;
case BeatSession.on_accepted:
// msg will be here
break;
default:
msg = "Unknown";
break;
}
}
catch (Exception ex)
{
throw ex;
}
// Override message
if (!String.IsNullOrEmpty(custom_message))
{
msg = custom_message;
}
return msg;
}
EDIT: Since you edited your question with the answer code, you should have any problem with your switch statement, take a look at the following screen shot.
If enum was actually an enum case a: would not pass a compile.
This works for me
enum myEnum {A, B, C};
public MainWindow()
{
InitializeComponent();
myEnum thisEnum = myEnum.B;
switch(thisEnum)
{
case myEnum.A:
// do something
break;
case myEnum.B:
// do something
break;
default:
break;
}
}
Fixed the problem. Here is what I did. I modified my Enum to be like this.
public enum BeatSession
{
on_ended=0,
on_new=1,
on_hold=2,
on_paused=3,
on_accepted=4,
on_answered=5,
on_timed_out=6,
on_hanged_up=7,
on_initiated=8,
unknown=9
}
So I think what happened was at some point during runtime or compile time the values on my Enum get's scrambled. So I tried setting the value manually and that did the trick.
Thanks Everyone for your reply.
maybe your code is like :
public static string GetStatusMessage(BeatSession status, string custom_message = "")
{
string msg = "";
try
{
switch (status)
{
case BeatSession.on_answered:
// msg will be here
case BeatSession.on_ended:
// msg will be here
break;
.....
if you pass BeatSession.on_answered then in swith (think you missed "break;") goes to BeatSession.on_ended.