Zapytanie do API z sortowaną listą.

0

Cześć :)
Piszę właśnie aplikację Unity, którą łączy się z API (ASP.NET Core). W aplikacji będę miał m.in. listę użytkowników. Chciałbym się zapytać was jak najlepiej komunikować się z API abym w jednym zapytaniu mógł wysłać informacje dotyczące filtrowania i sortowania użytkowników.
Moim pierwszym pomysłem było stworzenie HTTPRequest'a z jsonem, w którym zawarte będą Expression<Func<User, bool>> lecz niestety Json mi tego nie serializuje.

Przykładowo:

var tt = _context.User.Where(x => x.IsDeleted == false && x.Role == RoleSharedEnum.User).OrderBy(x => x.DateCreate);

Parametry where i order by chciałbym wysłać z aplikacji do Api.

Co możecie mi polecić do tego celu?

1

Jeżeli to byłyby dość proste warunki, bez dynamicznych operatorów to stosowałem coś takiego (z ręki pisane, nie wiem czy się kompiluje):

public class UserSearchPredicate
{
	public int? Age { get; set; }
	
	public int? Score { get; set; }
}
public List<Expression<Func<User, bool>> GetPredicates(UserSearchPredicate input)
{
	var predicates = new List<Expression<Func<User, bool>>();
	
	// jeżeli ktoś wprowadził jakąś wartość do kryteriów przeszukiwania
	if (input.Age != null)
	{
		predicates.Add(x => x.Age >= input.Age);
	}
	
	if (input.Score != null)
	{
		predicates.Add(x => x.Score >= input.Score);
	}
	
	return predicates;
}

IQueryable query = _context.User;

foreach (var predicate in predicates)
{
	query = query.Where(predicate);
}

var data = query.ToList();

Jeżeli chcesz jeszcze dynamicznie podawać operatory, to możesz obczaić temat Expression Trees / Dynamic Predicate Builder

https://tyrrrz.me/blog/expression-trees

typu

var param = Expression.Parameter(typeof(SomeObject), "p");
var exp = Expression.Lambda<Func<SomeObject, bool>>(
    Expression.Equal(
        Expression.Property(param, "Name"),
        Expression.Constant("Bob")
    ),
    param
);
var query = someObj.Where(exp);

i te Expression.Equal, Expression.GreaterThan itd. w zależności od operatora porównania

1

Paradoksalnie zapytam: a dlaczego REST, skoro jest "logicznie" za słaby.

W niesłusznie porzuconym RPC jest wiele zalet.
Ze współczesnych implementacji RPC można wymienić Apache Thrift czy GRPC (Google Protobuf)

0

@AnyKtokolwiek:

g/RPC? może GraphQL? on się chyba idealnie nadaje do takich rzeczy, bo po to został stworzony - Dynamic Querying :P

GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

0

GraphQL - raczej nie mogę użyć (ograniczenia Unity), RPC - nigdy nie korzystałem, jestem raczej z tym początkujących :)
Napiszę bardziej precyzyjnie :)

public class UserSharedModel: BaseTableModel
    {
        public string Nick { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
        public RoleSharedEnum Role { get; set; }
    }

To jest mój model użytkownika.
Po stronie aplikacji (UNITY) chcę wykonać przykładowe pobranie listy użytkowników, gdzie ich rola to "User" i zwrócona zostanie mi lista tylko tych użytkowników spełniających warunek.

 public void Develop_GetAllUser(UserListApiRequestModel userRequest, Action<List<UserListItemApiModel>> onCompleted)
        {
            Task.Factory.StartNew(() =>
            {
                HttpClient client = new HttpClient();
                try
                {
                    var request = new HttpRequestMessage(HttpMethod.Post, new Uri(AppConfiguration.Instance.ServerConnectionString + "User/Develop_GetAllUser"));
                    request.Headers.Add(HttpHeaderHelper.Session, AppContainerManager.Instance.UserSession);

                    //var json = JsonConvert.SerializeObject(userRequest);
                    //var stringContent = new StringContent(json, Encoding.UTF8, "application/json");
                    //request.Content = stringContent;

                    var clientResponse = client.SendAsync(request).Result;

                    var clientData = clientResponse.Content.ReadAsStringAsync();

                    var clientObject = JsonConvert.DeserializeObject<List<UserListItemApiModel>> (clientData.Result);

                    onCompleted.Invoke(clientObject);
                }
                catch (Exception ex)
                {
                    var Error = ex;
                    onCompleted.Invoke(null);
                }
                finally
                {
                    client.Dispose();
                }
            });
        }

W zapytaniu chciałbym przesłać predykat, który po stronie API wykonałby mi coś takiego:

var t = _context.User.Where(x=>x.Role == RoleSharedEnum.User).ToList();
0

@GreenGooblin:

GraphQL - raczej nie mogę użyć (ograniczenia Unity),

Zaznaczę od razu, że GraphQL to jest tutaj overkillem, ale:

Jeżeli możesz wysłać HTTP Request z poziomu Unity, to GraphQL raczej też możesz odpytać, bo obsługa GraphQL jest po stronie aplikacji webowej.

Tu możesz się pobawić GraphQLem i zobaczyć co tam jest wysyłane.

https://lucasconstantino.github.io/graphiql-online/

screenshot-20200711173044.png

Tu jest Body zapytania, czyli właściwie to moje Query.

screenshot-20200711173117.png

A jeżeli chodzi o skorzystanie z podejścia z dynamicznym budowaniem predykatów, to wydaje mi się że ci odpowiedziałem w pierwszym poście, jeżeli coś jest niejasne, to pytaj :P

Wysyłasz zapytanie z danymi w swoim UserSharedModel i później na podstawie wstawionych tam wartości generujesz warunki, tyle :P

0

Tu masz odpowiedź https://stackoverflow.com/a/233505/10671539 ale to już oranie refleksją.

1 użytkowników online, w tym zalogowanych: 0, gości: 1