Método de API de web genérico -- # campo con generics campo con asp.net-web-api campo con asp.net-web-api2 campo con asp.net-web-api-routing camp Relacionados El problema

Generic Web Api method


7
vote

problema

Español

Tengo algunas clases como CustomerModel o CustomerDetailsModel que se detienen desde ModelBase .

tampoco quiero introducir subclases para cada modelo.

en un caso tiene un método posterior aleje.

para que pueda crear manualmente varias rutas para llamar a un método que se vea

  Handle<T>(T model) where T : ModelBase   

Se diferencian solo en el camino. Por ejemplo:

  baseurl/api/customer => CustomerModel baseurl/api/customerdetails => CustomerDetailsModel   

Quiero implementar un método de API web genérico como

  [HttpPost] void Post<T>(T model) where T : ModelBase   

Si simplemente creo un método genérico, obtuve una excepción que me dice que el método de la API web no pudo tener métodos genéricos. Pero hace algún tiempo, he visto una implementación con la API web v1 usando algún tipo de mecanismos de búsqueda personalizados para manejar esto. Pero ya no puedo entenderlo.

Como solución alternativa, creó una callwrapper que determina el tipo e invoca un método genérico interno, pero esto se siente bastante feo

   public async Task<IHttpActionResult> Post(string id, string moduleType)         {             await AsyncGenericCallWrapper(moduleType); ...   

Sería una gran mantequilla tener el controlador genérico mencionado anteriormente.

    private async Task AsyncGenericCallWrapper(string moduleType)         {             Type type = GetModuleType(moduleType);             var content = await Request.Content.ReadAsStringAsync();             var instance = JsonConvert.DeserializeObject(content, type);              MethodInfo method = this.GetType().GetMethod("InternalGenericMethod", BindingFlags.NonPublic | BindingFlags.Instance);             MethodInfo generic = method.MakeGenericMethod(type);             var result = generic.Invoke(this, new object[] { instance }) as Task;              await result;         }   

Puedo imaginarme para tener un atributo personalizado que asigna los tipos como

  __text:001C6DC0 ; -[NSWindow _windowMovedToRect:] __text:001C6DC0 __NSWindow__windowMovedToRect__ proc near ; DATA XREF: __inst_meth:00993418o __text:001C6DC0 __text:001C6DC0 var_C           = dword ptr -0Ch __text:001C6DC0 arg_0           = dword ptr  8 __text:001C6DC0 arg_8           = dword ptr  10h __text:001C6DC0 arg_C           = dword ptr  14h __text:001C6DC0 arg_10          = dword ptr  18h __text:001C6DC0 arg_14          = dword ptr  1Ch __text:001C6DC0 __text:001C6DC0                 push    ebp __text:001C6DC1                 mov     ebp, esp __text:001C6DC3                 push    esi __text:001C6DC4                 push    ebx __text:001C6DC5                 sub     esp, 30h __text:001C6DC8                 call    $+5 __text:001C6DCD                 pop     ebx __text:001C6DCE                 mov     esi, [ebp+arg_0] __text:001C6DD1                 lea     eax, [ebp+var_C] __text:001C6DD4                 mov     [esp], eax __text:001C6DD7                 call    _PSbuttondown __text:001C6DDC                 mov     edx, [ebp+var_C] __text:001C6DDF                 test    edx, edx __text:001C6DE1                 jz      short loc_1C6E1D __text:001C6DE3                 mov     eax, [esi+80h] __text:001C6DE9                 or      dword ptr [eax+0B8h], 1000000h __text:001C6DF3                 mov     eax, [ebp+arg_8] __text:001C6DF6                 mov     edx, [ebp+arg_C] __text:001C6DF9                 mov     [esp+8], eax __text:001C6DFD                 mov     [esp+0Ch], edx __text:001C6E01                 mov     eax, [esi+8] __text:001C6E04                 mov     edx, [esi+0Ch] __text:001C6E07                 mov     [esp], eax __text:001C6E0A                 mov     [esp+4], edx __text:001C6E0E                 call    _NSEqualPoints __text:001C6E13                 test    al, al __text:001C6E15                 jnz     loc_1C6ED6 __text:001C6E1B                 jmp     short loc_1C6E50 __text:001C6E1D ; --------------------------------------------------------------------------- __text:001C6E1D __text:001C6E1D loc_1C6E1D:                             ; CODE XREF: -[NSWindow _windowMovedToRect:]+21j __text:001C6E1D                 mov     eax, [ebp+arg_8] __text:001C6E20                 mov     [esp+8], eax __text:001C6E24                 mov     eax, [ebp+arg_C] __text:001C6E27                 mov     [esp+0Ch], eax __text:001C6E2B                 mov     eax, [ebp+arg_10] __text:001C6E2E                 mov     [esp+10h], eax __text:001C6E32                 mov     eax, [ebp+arg_14] __text:001C6E35                 mov     [esp+14h], eax __text:001C6E39                 mov     eax, ds:(off_926DC8 - 1C6DCDh)[ebx] __text:001C6E3F                 mov     [esp+4], eax __text:001C6E43                 mov     [esp], esi __text:001C6E46                 call    _objc_msgSend __text:001C6E4B                 jmp     loc_1C6ED6 __text:001C6E50 ; --------------------------------------------------------------------------- __text:001C6E50 __text:001C6E50 loc_1C6E50:                             ; CODE XREF: -[NSWindow _windowMovedToRect:]+5Bj __text:001C6E50                 mov     eax, [ebp+arg_8] __text:001C6E53                 mov     [esp+8], eax __text:001C6E57                 mov     eax, [ebp+arg_C] __text:001C6E5A                 mov     [esp+0Ch], eax __text:001C6E5E                 mov     eax, [ebp+arg_10] __text:001C6E61                 mov     [esp+10h], eax __text:001C6E65                 mov     eax, [ebp+arg_14] __text:001C6E68                 mov     [esp+14h], eax __text:001C6E6C                 mov     eax, ds:(off_91D198 - 1C6DCDh)[ebx] __text:001C6E72                 mov     [esp+4], eax __text:001C6E76                 mov     [esp], esi __text:001C6E79                 call    _objc_msgSend __text:001C6E7E                 mov     eax, ds:(off_91A4B8 - 1C6DCDh)[ebx] __text:001C6E84                 mov     [esp+4], eax __text:001C6E88                 mov     eax, ds:(off_928EE8 - 1C6DCDh)[ebx] __text:001C6E8E                 mov     [esp], eax __text:001C6E91                 call    _objc_msgSend __text:001C6E96                 mov     [esp+0Ch], esi __text:001C6E9A                 mov     edx, ds:(_NSWindowDidMoveNotification_ptr - 1C6DCDh)[ebx] __text:001C6EA0                 mov     edx, [edx] __text:001C6EA2                 mov     [esp+8], edx __text:001C6EA6                 mov     edx, ds:(off_91B0DC - 1C6DCDh)[ebx] __text:001C6EAC                 mov     [esp+4], edx __text:001C6EB0                 mov     [esp], eax __text:001C6EB3                 call    _objc_msgSend __text:001C6EB8                 mov     eax, ds:(_NSAccessibilityMovedNotification_ptr - 1C6DCDh)[ebx] __text:001C6EBE                 mov     eax, [eax] __text:001C6EC0                 mov     [esp+8], eax __text:001C6EC4                 mov     eax, ds:(off_91B030 - 1C6DCDh)[ebx] __text:001C6ECA                 mov     [esp+4], eax __text:001C6ECE                 mov     [esp], esi __text:001C6ED1                 call    _objc_msgSend __text:001C6ED6 __text:001C6ED6 loc_1C6ED6:                             ; CODE XREF: -[NSWindow _windowMovedToRect:]+55j __text:001C6ED6                                         ; -[NSWindow _windowMovedToRect:]+8Bj __text:001C6ED6                 add     esp, 30h __text:001C6ED9                 pop     ebx __text:001C6EDA                 pop     esi __text:001C6EDB                 leave __text:001C6EDC                 retn __text:001C6EDC __NSWindow__windowMovedToRect__ endp 0  

Con esto podría crear rutas para cada atributo, pero aún así el método se invoca ya que es genérico, ni sé cómo interferir el mecanismo de deserialización

¿Alguien puede decirme cómo implementar ese GenericWebApimethod?

Original en ingles

I've some classes like CustomerModel or CustomerDetailsModel which are inherting from ModelBase.

Also i don't want to introduce subclasses for each modeltype.

In one case have a post method foreach.

So i could manually create multiple routes to call a method which looks like

Handle<T>(T model) where T : ModelBase 

They only differ in the path the were called. For example:

baseurl/api/customer => CustomerModel baseurl/api/customerdetails => CustomerDetailsModel 

I want to implement a generic web api method like

[HttpPost] void Post<T>(T model) where T : ModelBase 

If I simply create a generic method i got an exception which tells me that the web api method could not have generic methods. But sometime ago I've seen an implementation with web api v1 using some kind of custom lookup mechanisms to handle this. But i can't figure out it anymore.

As a workaround I created a callwrapper which determines the type and invokes a internal generic method, but this feels quite ugly

 public async Task<IHttpActionResult> Post(string id, string moduleType)         {             await AsyncGenericCallWrapper(moduleType); ... 

It would be much butter to have the above mentioned generic controllerr.

  private async Task AsyncGenericCallWrapper(string moduleType)         {             Type type = GetModuleType(moduleType);             var content = await Request.Content.ReadAsStringAsync();             var instance = JsonConvert.DeserializeObject(content, type);              MethodInfo method = this.GetType().GetMethod("InternalGenericMethod", BindingFlags.NonPublic | BindingFlags.Instance);             MethodInfo generic = method.MakeGenericMethod(type);             var result = generic.Invoke(this, new object[] { instance }) as Task;              await result;         } 

I can image to have a custom Attribute which maps the types like

[GenericRoute("/customer", typeof(CustomerModel)] [GenericRoute("/customerDetail", typeof(CustomerDetailModel)] void Post<T>(T model) where T : ModelBase 

With this i could create routes for each attribute, but still the method now get invoked as it is generic , nor i know how to interfer the deserialization mechanism

Can anyone tell me how to implement that GenericWebAPiMethod?

              
 
 

Lista de respuestas

12
 
vote

El problema con este enfoque es que la API web no sabe cómo deserializar el objeto.

En lugar de tener un método genérico, puede crear un controlador genérico.

Digamos que su modelo es así:

  public class OpenClass {      public static void main(String args[]) {         new OpenClass().testIt();     }      public void testIt() {         Workbook w;         JFileChooser chooser = new JFileChooser();          int option = chooser.showOpenDialog(null);          //CREATE TWO CELL OBJECTS         Cell cell1, cell2;         if (option == JFileChooser.APPROVE_OPTION) {             try {                 w = Workbook.getWorkbook(chooser.getSelectedFile());                  Sheet sheet = w.getSheet(0);                  //ITERATE BY ROWS                 for (int i = 0; i < sheet.getRows(); i++) {                      //GET AND CHECK COLUMN1 VALUE                     cell1 = sheet.getCell(0, i);                     if (checkIfNumber(cell1.getContents().toString()) == false)                         continue;                      //GET CHECK COLUMN2 VALUE                     cell2 = sheet.getCell(1, i);                     CellType type = cell2.getType();                      if ((type == CellType.LABEL) || (type == CellType.NUMBER)) {                         String query = "INSERT INTO student (USN,Name)"                                 + "VALUES('" + cell1.getContents() + "','"                                 + cell2.getContents() + "')";                         System.out.println(query);                         //RUN YOUR QUERY HERE!                     }                 }             } catch (BiffException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             } catch (IOException e) {                 // TODO Auto-generated catch block                 e.printStackTrace();             }         }      }      private boolean checkIfNumber(String string) {         try {             double d = Double.parseDouble(string);             //System.out.print(d);             return true;         } catch (NumberFormatException ne) {             return false;         }      }  } 9  

Puede escribir un controlador genérico para lidiar con las clases que heredan de ModelBase:

  JSON.stringify0  
 

The problem with this approach is that the Web API does not know how to deserialize the object.

Rather than having a generic method, you can create a generic controller.

Let's say your model is like that:

public abstract class ModelBase{ }  public class CustomerModel : ModelBase {}  public class CustomerDetailsModel: ModelBase { } 

You can write a generic controller to deal with classes that inherits from ModelBase :

public class ModelBaseController<T> : ApiController where T : ModelBase  {     [HttpPost]     public void Post(T model)     {         ...     } }  public class CustomerModelController : ModelBaseController<CustomerModel> { }  public class CustomerDetailsModelController : ModelBaseController<CustomerDetailsModel> { } 
 
 
   
   

Relacionados problema

2  MVC 4 Web API Route 404 problema  ( Mvc 4 web api route 404 issue ) 
Tengo un proyecto de API de la Web de MVC 4 Plain-Vanilla, creado usando VS2012. Los (/ api / valores) funcionan fuera de la casilla en el localhost pero no...

5  ¿Cómo usar la misma ruta con diferentes tipos de parámetros?  ( How to use the same route with different parameter types ) 
Tengo un controlador API con dos acciones diferentes que toman diferentes tipos de parámetros. // GET: users/sample%40email.com [Route("users/{emai...

0  Mapa dos rutas diferentes a la misma acción del controlador  ( Map two different routes to the same controller action ) 
Estoy trabajando en la extensión del ejemplo en: https: / /docs.asp.net/en/latest/tutorials/first-web-api.html Tienen una API de TODO: Update EmployeeSit...

1  Ayuda WEBAPI y rutas múltiples  ( Webapi help and multipe routes ) 
i hav un proyecto API web (C #, ASP.NET MVC) donde debo poder llamar a las acciones, usando la plantilla API / {controller} / {acción} / {id} y api / {control...

257  Se encontraron múltiples acciones que coinciden con la solicitud en la API web  ( Multiple actions were found that match the request in web api ) 
Sigo recibiendo este error cuando intento tener 2 métodos "Obtener" Se encontraron múltiples acciones que coinciden con la solicitud: WEBAPI He estado m...

64  Enrutamiento con múltiples métodos Obtener en ASP.NET WEB API  ( Routing with multiple get methods in asp net web api ) 
Estoy usando la API web con ASP.NET MVC, y soy muy nuevo en él. He pasado por alguna demo en el sitio web de ASP.NET y estoy tratando de hacer lo siguiente. ...

8  API web Obtener plantilla de ruta desde el controlador interno  ( Web api get route template from inside handler ) 
Busqué mucho antes de poner las preguntas aquí, pero cuanto más busco, más confundido que recibo. Así que he creado un manejador y estoy tratando de obtener...

0  Enrutamiento personalizado en la API web 2. No se puede llegar al método del controlador  ( Custom routing in web api 2 failing to reach controller method ) 
Tengo un método dentro de mi controlador que estoy tratando de alcanzar: [HttpPost, ActionName("UpdateTitle")] public IHttpActionResult UpdateTitle(Guid pl...

0  ¿Por qué mi enrutamiento de la API web no funciona?  ( Why is my web api routing not working ) 
Tengo el siguiente código en mi API, public static void Register(HttpConfiguration config) { // Web API routes config.MapHttpAttrib...

16  ¿Habilitación de CORS con solicitudes de PUT / POST / POST?  ( Enabling cors with webapi put post requests ) 
He intentado seguir este post, pero todavía no estoy allí: CORS Soporte para poner y eliminar con APP.NET WEB API en mi web.config tengo lo siguiente: ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos