ASP .NET MVC 4 WebApi : OData 쿼리를 수동으로 처리
나는 웹 서비스를 사용하여 만든 WebAPI 내가 WebAPI가 자동으로 작동하는의 상단에 레이어가 처리하는 알 ASP .NET MVC (4)에 의해 제공을 하나로, OData 쿼리 (예 : $filter
, $top
, $skip
나 자신에 의해 필터링을 처리하는 경우),하지만 무엇을 ?
단순히 데이터베이스에서 데이터를 반환하는 것이 아니라 일부 속성을 추가하고 일부 변환을 만드는 또 다른 레이어가 있습니다. 따라서 모든 데이터를 쿼리하고 변환 한 다음 OData 필터링을 위해 WebAPI 클래스로 반환하는 것은 좋지 않습니다. 충분히. 물론 매우 느리고 일반적으로 엉터리 아이디어입니다.
내 WebAPI 진입 점에서 데이터를 가져오고 변환하기 위해 호출하는 함수로 OData 쿼리 매개 변수 를 전파 하는 방법이 있습니까?
예를 들어 GET /api/people?$skip=10&$top=10
은 서버에서 호출합니다.
public IQueryable<Person> get() {
return PersonService.get(SomethingAboutCurrentRequest.CurrentOData);
}
그리고 PersonService
:
public IQueryable<Person> getPeople(var ODataQueries) {
IQueryable<ServerSidePerson> serverPeople = from p in dbContext.ServerSidePerson select p;
// Make the OData queries
// Skip
serverPeople = serverPeople.Skip(ODataQueries.Skip);
// Take
serverPeople = serverPeople.Take(ODataQueries.Take);
// And so on
// ...
// Then, convert them
IQueryable<Person> people = Converter.convertPersonList(serverPeople);
return people;
}
나는 방금이 오래된 게시물을 우연히 발견했으며 이제 OData 쿼리를 직접 처리하는 것이 매우 쉽기 때문에이 답변을 추가하고 있습니다. 예를 들면 다음과 같습니다.
[HttpGet]
[ActionName("Example")]
public IEnumerable<Poco> GetExample(ODataQueryOptions<Poco> queryOptions)
{
var data = new Poco[] {
new Poco() { id = 1, name = "one", type = "a" },
new Poco() { id = 2, name = "two", type = "b" },
new Poco() { id = 3, name = "three", type = "c" }
};
var t = new ODataValidationSettings() { MaxTop = 2 };
queryOptions.Validate(t);
//this is the method to filter using the OData framework
//var s = new ODataQuerySettings() { PageSize = 1 };
//var results = queryOptions.ApplyTo(data.AsQueryable(), s) as IEnumerable<Poco>;
//or DIY
var results = data;
if (queryOptions.Skip != null)
results = results.Skip(queryOptions.Skip.Value);
if (queryOptions.Top != null)
results = results.Take(queryOptions.Top.Value);
return results;
}
public class Poco
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
URL의 쿼리는 작업이 반환하는 IQueryable에 대해 실행되는 LINQ 식 트리로 변환됩니다. 식을 분석하고 원하는 방식으로 결과를 제공 할 수 있습니다. 단점은 매우 쉽지 않은 IQueryable을 구현해야한다는 것입니다. 관심이있는 경우이 블로그 게시물 시리즈를 살펴보세요. http://blogs.msdn.com/b/vitek/archive/2010/02/25/data-services-expressions-part-1-intro.aspx . WCF 데이터 서비스에 대해 설명하지만 웹 API에서 사용하는 필터 식은 매우 유사합니다.
Web-api를 사용하는 한 가지 방법은 http://www.asp.net/web-api/overview/working-with-http/http-message-handlers 고객 메시지 처리기를 사용하는 것입니다 .
아래와 같은 커스텀 핸들러를 작성하세요 :
public class CustomHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken).ContinueWith(
(task) =>
{
HttpResponseMessage response = task.Result;
var persons = response.Content.ReadAsAsync<IQueryable<Person>>().Result;
var persons2 = new List<Person>(); //This can be the modified model completely different
foreach (var item in persons)
{
item.Name = "changed"; // here you can change the data
//persons2.Add(....); //Depending on the results modify this custom model
}
//overwrite the response
response = new HttpResponseMessage<IEnumerable<Person>>(persons2);
return response;
}
);
}
}
global.asax.cs에 등록
애플리케이션 클래스의 방법 :
static void Configure(HttpConfiguration config)
{
config.MessageHandlers.Add(new CustomHandler());
}
protected void Application_Start()
{
....
.....
//call the configure method
Configure(GlobalConfiguration.Configuration);
}
I did something like this with WCF Data Services and asp.net mvc 3.5 but it was a bit of a kludge.
The first step is to rewrite the path so that the skip and top options don't get applied twice, once by you and once by the runtime.
I did the rewriting with an HttpModule. In your BeginRequest method you'd have code like this:
HttpApplication app = (HttpApplication)sender;
if (HttpContext.Current.Request.Path.Contains(YOUR_SVC))
{
if (app.Request.Url.Query.Length > 0)
{
//skip questionmark
string queryString = app.Request.Url.Query.Substring(1)
.Replace("$filter=", "filter=")
.Replace("$orderby=", "orderby=")
.Replace("$top=", "top=")
.Replace("$skip=", "skip=");
HttpContext.Current.RewritePath(app.Request.Path, "", queryString);
}
}
Then just examine the query string and pluck out the parameters you need.
if (HttpContext.Current.Request.QueryString["filter"] != null)
var filter = HttpContext.Current.Request.QueryString["filter"] as string;
Then split the filter string and parse it into a sql statement or any other db commands. I was using NHibernate in my case. I was also able to limit what filter commands I supported which made things easier. I didn't do groupings for example. Mostly just the comparison operators.
There's a list of filter operators at OData.org. Split the string by "and" and "or" into individual clauses. Split each clause by a space and you should get a 3 element array with the property name in [0] the operator in [1] and the value in [2].
The clauses will be in terms of a Person but I'm assuming you'll be able to convert them into something that will pull the right results out of the db.
I ended up abandoning this approach since it won't work for POSTS. I had to write my own Linq provider but writing my own filter string parser made that easier to understand.
ReferenceURL : https://stackoverflow.com/questions/10781309/asp-net-mvc-4-webapi-manually-handle-odata-queries
'programing' 카테고리의 다른 글
java.lang 네이티브 메서드에 대한 소스 코드는 어디에서 찾을 수 있습니까? (0) | 2021.01.16 |
---|---|
Mac OS X에서 가장 좋아하는 디스어셈블러 도구는 무엇입니까? (0) | 2021.01.16 |
다른 클래스에서 현재 또는 주요 활동을 참조하는 방법 (0) | 2021.01.16 |
Dockerfile-ENV를 명령 결과로 설정 (0) | 2021.01.16 |
Android : Google 서버를 사용하지 않는 음성 인식 (0) | 2021.01.16 |