diff --git a/Mf.Razor.Entity/Interfaces/IServiceLocator.cs b/Mf.Razor.Entity/Interfaces/IServiceLocator.cs
index d5ae5bd..f734d74 100644
--- a/Mf.Razor.Entity/Interfaces/IServiceLocator.cs
+++ b/Mf.Razor.Entity/Interfaces/IServiceLocator.cs
@@ -8,6 +8,5 @@ namespace Mf.Razor.Entity.Interfaces
{
public interface IServiceLocator
{
-
}
}
diff --git a/Mf.Razor.Entity/Mf.Razor.Entity.csproj b/Mf.Razor.Entity/Mf.Razor.Entity.csproj
index 237d661..037ba6e 100644
--- a/Mf.Razor.Entity/Mf.Razor.Entity.csproj
+++ b/Mf.Razor.Entity/Mf.Razor.Entity.csproj
@@ -6,4 +6,8 @@
enable
+
+
+
+
diff --git a/Mf.Razor.Entity/Services/FluentQuery.cs b/Mf.Razor.Entity/Services/FluentQuery.cs
new file mode 100644
index 0000000..9937bfb
--- /dev/null
+++ b/Mf.Razor.Entity/Services/FluentQuery.cs
@@ -0,0 +1,231 @@
+using System.Linq.Expressions;
+using System.Net.Http.Headers;
+using System.Net.Http.Json;
+using Mf.Core.SubEntities.QueryModel;
+
+namespace Mf.Razor.Entity.Services;
+
+public class FluentQuery
+ {
+ private HttpClient httpClient;
+
+ public FluentQuery(HttpClient httpClient)
+ {
+ this.httpClient = httpClient;
+ }
+ private readonly QueryRequest _request = new();
+
+ public FluentQuery Include(Expression> expression)
+ {
+ var propName = GetPropertyPath(expression.Body);
+ _request.Includes.Add(propName);
+ return this;
+ }
+
+ public void Clear()
+ {
+ _request.Filters = new();
+ _request.Includes = new();
+ _request.Take = null;
+ _request.Skip = null;
+ _request.ObjectType = null;
+
+ }
+
+ public FluentQuery Where(Expression> expression)
+ {
+ if (expression.Body is BinaryExpression binary)
+ {
+ var left = GetPropertyName((MemberExpression)binary.Left);
+ var op = GetOperator(binary.NodeType);
+ var right = Expression.Lambda(binary.Right).Compile().DynamicInvoke()?.ToString();
+
+ _request.Filters.Add(new Filter
+ {
+ Field = left,
+ Operator = op,
+ Value = right
+ });
+ }
+ else if (expression.Body is MethodCallExpression methodCall)
+ {
+ var method = methodCall.Method.Name;
+
+ if (method is "Contains" or "StartsWith" or "EndsWith")
+ {
+ var field = GetPropertyName(methodCall.Object ?? methodCall.Arguments[0]);
+ var value = Expression.Lambda(methodCall.Arguments[^1]).Compile().DynamicInvoke()?.ToString();
+
+ _request.Filters.Add(new Filter
+ {
+ Field = field,
+ Operator = method, // توی سرور بررسی کن با این نام یا تبدیل کن
+ Value = value
+ });
+ }
+ else
+ {
+ throw new NotSupportedException($"Unsupported method: {method}");
+ }
+ }
+
+
+
+
+
+ return this;
+ }
+
+ public FluentQuery Skip(int count)
+ {
+ _request.Skip = count;
+ return this;
+ }
+
+ public FluentQuery Take(int count)
+ {
+ _request.Take = count;
+ return this;
+ }
+
+
+
+ public QueryRequest Build() => _request;
+
+ public async Task PostAsync(string token)
+ {
+ try
+ {
+ httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
+ _request.ObjectType = typeof(T).AssemblyQualifiedName;
+ var result = await httpClient.PostAsJsonAsync("api/generic/get", _request);
+ return result;
+ }
+ catch (Exception ex)
+ {
+ return new HttpResponseMessage();
+ }
+ finally
+ {
+ Clear();
+ }
+
+
+ }
+
+ public async Task> ResultPostAsync(string token)
+ {
+ try
+ {
+ var result = await PostAsync(token);
+ //var ssss = await result.Content.ReadFromJsonAsync>();
+ if (result != null && await result.Content.ReadFromJsonAsync>() is List rr)
+ {
+ return rr;
+ }
+ }
+ catch (Exception ex)
+ {
+ //ServiceLocator.Log($"Error read from api {ex.Message}");
+ }
+ return new List();
+ }
+
+
+ public async Task InsertAsync(T model,string token)
+ {
+ try
+ {
+ httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
+ AlterRequest req = new AlterRequest() { Model = model, ObjectType = typeof(T).AssemblyQualifiedName };
+ return await httpClient.PostAsJsonAsync("api/generic/insert", req);
+ }
+ finally
+ {
+
+ Clear();
+ }
+
+ }
+
+
+ public async Task UpdateAsync(T model,string token)
+ {
+ try
+ {
+ httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
+ AlterRequest req = new AlterRequest() { Model = model, ObjectType = typeof(T).AssemblyQualifiedName };
+ return await httpClient.PostAsJsonAsync("api/generic/update", req);
+ }
+ finally
+ {
+ Clear();
+ }
+
+ }
+
+ public async Task DeleteAsync(T model,string token)
+ {
+ try
+ {
+ httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
+ AlterRequest req = new AlterRequest() { Model = model, ObjectType = typeof(T).AssemblyQualifiedName };
+ return await httpClient.PostAsJsonAsync("api/generic/delete", req);
+ }
+ finally
+ {
+ Clear();
+ }
+
+ }
+
+
+
+ private string GetOperator(ExpressionType type)
+ {
+ return type switch
+ {
+ ExpressionType.Equal => "=",
+ ExpressionType.GreaterThan => ">",
+ ExpressionType.GreaterThanOrEqual => ">=",
+ ExpressionType.LessThan => "<",
+ ExpressionType.LessThanOrEqual => "<=",
+ ExpressionType.NotEqual => "!=",
+ _ => throw new NotSupportedException("Unsupported operator")
+ };
+ }
+
+
+
+ private string GetPropertyName(Expression expression)
+ {
+ return expression switch
+ {
+ MemberExpression me => me.Member.Name,
+ UnaryExpression ue when ue.Operand is MemberExpression me => me.Member.Name,
+ _ => throw new NotSupportedException("Unsupported expression")
+ };
+ }
+
+
+ private string GetPropertyPath(Expression expression)
+ {
+ if (expression is UnaryExpression unaryExpr && unaryExpr.Operand is MemberExpression)
+ {
+ expression = unaryExpr.Operand;
+ }
+
+ var members = new Stack();
+
+ while (expression is MemberExpression member)
+ {
+ members.Push(member.Member.Name);
+ expression = member.Expression;
+ }
+
+ return string.Join(".", members);
+ }
+
+
+ }
+
diff --git a/Mf.Razor.Entity/Services/RouteConfig.cs b/Mf.Razor.Entity/Services/RouteConfig.cs
new file mode 100644
index 0000000..ce93b4b
--- /dev/null
+++ b/Mf.Razor.Entity/Services/RouteConfig.cs
@@ -0,0 +1,10 @@
+namespace Mf.Razor.Entity.Services;
+
+public class RouteConfig
+{
+ public string GenericApiGetRequest { get; set; }
+ public string GenericApiGetItemRequest { get; set; }
+ public string GenericApiDeleteRequest { get; set; }
+ public string GenericApiUpdateRequest { get; set; }
+ public string GenericApiCreateRequest { get; set; }
+}
\ No newline at end of file