PUT Request from iOS using OpenAccess Web API Service

5 posts, 0 answers
  1. Galobart
    Galobart avatar
    4 posts
    Member since:
    Mar 2010

    Posted 08 Jan 2013 Link to this post

    regards,

    I have a web service API generated by OpenAccess wizard. I can receive data without problems, but I need to update the data from the device.

    I have this in my controller.partial.cs.:

    public virtual HttpResponseMessage Put(TuPrevencion.Auditoria entity)
    {
        Auditoria auditoria = (from c in dbContext.Auditorias where c.Id == entity.Id select c).FirstOrDefault();
        auditoria.Comentarios = entity.Comentarios;
        ...
     
        dbContext.SaveChanges();
     
        return Request.CreateResponse(HttpStatusCode.NoContent);
    }

    And working perfectly from a windows project using HttpResponseMessage:

    var entity = new Auditoria() { Id = 31, Comentarios = "Test", ...};
    Uri gizmoUri = null;
     
    HttpResponseMessage response = client.PutAsJsonAsync("api/auditorias", entity).Result;
     
     
    var resultTask = client.PutAsJsonAsync("api/auditorias", entity).Result.Content.ReadAsStringAsync();
    Console.WriteLine("{0} ", resultTask.ToString());
    Console.ReadLine();
    if (response.IsSuccessStatusCode)
    {
        gizmoUri = response.Headers.Location;
    }
    else
    {
        Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
        Console.ReadLine();
    }

    But i don't know how extract the JSon generated. I need to see it to compose the correct code in iOS, and I cant find documentation about it. May be is not relevant to put iOS code here, but I add it just in case.

    NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:
                          @"Test", @"Comentarios", @"31", @"Id",  nil];
    NSDictionary *data2 = [NSDictionary dictionaryWithObjectsAndKeys: data, @"entity", nil];
    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data2 options:NSJSONWritingPrettyPrinted error:&error];
     
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    NSLog(@"JSON Output: %@", jsonString);
     
    NSString *_urlString = [NSString  stringWithFormat: @"https://url.com:449/api/auditorias"];
    NSURL *_url = [NSURL URLWithString:_urlString];
    NSMutableURLRequest* _request = [[Authentication sharedInstance ] _request:_url];
     
    NSData *requestData = [NSData dataWithBytes:[jsonString UTF8String] length:[jsonString length]];
     
    [_request setHTTPMethod:@"PUT"];
    [_request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [_request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
    [_request setHTTPBody: requestData];
     
    NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:_request delegate:self];
    if (connection) {
        receivedData = [NSMutableData data];
    }

    Thanks in advance!
  2. Hristo Marinov
    Admin
    Hristo Marinov avatar
    13 posts

    Posted 10 Jan 2013 Link to this post

    Hello Galobart,

    The Put method from the default generated Web API Service from OpenAccess does not retrieve content when it is invoked. The result is only an HttpResponseMessage containing a status code:

    return Request.CreateResponse(HttpStatusCode.NoContent);

    In that way on the client side when this method is invoked, the container for the received data will be empty.

    In case this doesn't answer your question, could you please describe in further details what do you want to achieve? We will try to provide some guidelines regarding how to extend the generated service to meet your needs.

    I am looking forward to your feedback.

    Greetings,
    Hristo Marinov
    the Telerik team
    Q3'12 SP1 of OpenAccess ORM packs Multi-Table Entities mapping support. Check it out.
  3. DevCraft banner
  4. Galobart
    Galobart avatar
    4 posts
    Member since:
    Mar 2010

    Posted 10 Jan 2013 Link to this post

    Thanks for your reply,

    I change the service code for receive not empty data in any situation:

    public virtual HttpResponseMessage Put(TuPrevencion.Auditoria entity)
    {
        if (entity == null)
            throw new HttpResponseException(HttpStatusCode.BadRequest);
     
        try
        {
            Auditoria auditoria = (from c in dbContext.Auditorias where c.Id == entity.Id select c).FirstOrDefault();
            auditoria.Comentarios = entity.Comentarios;
             
            .......
     
            dbContext.SaveChanges();
     
            return Request.CreateResponse(HttpStatusCode.Accepted);
        }
        catch(Exception ex)
        {
            return Request.CreateResponse(HttpStatusCode.InternalServerError);
        }
    }


    And the response still empty with both json sended:

        NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:
                              @"TestPOST", @"Comentarios", @"31", @"Id",
                              auditoria.empresa, @"EmpresaId", auditoria.cerrada, @"Cerrada", auditoria.visita_periodica, @"VisitaPeriodica",
                              nil];
        NSDictionary *data2 = [NSDictionary dictionaryWithObjectsAndKeys: data, @"entity", nil];
     
    ------- OUTPUT-------
     {
      "entity" : {
        "Cerrada" : 1,
        "EmpresaId" : 29,
        "Comentarios" : "TestPUT",
        "VisitaPeriodica" : 1,
        "Id" : "31"
      }
    }

    2013-01-10 10:50:05.610 PRL[1015:11603] data=(null)

    And:

        NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:
                              @"TestPOST", @"Comentarios", @"31", @"Id",
                              auditoria.empresa, @"EmpresaId", auditoria.cerrada, @"Cerrada", auditoria.visita_periodica, @"VisitaPeriodica",
                              nil];
     
     
    -----OUTPUT-----
     
    {
      "Cerrada" : 1,
      "EmpresaId" : 29,
      "Comentarios" : "TestPOST",
      "VisitaPeriodica" : 1,
      "Id" : "31"
    }
     
    2013-01-10 10:56:55.104 PRL[1042:11603] data=(null)

    So, may be the problem is in header.  I send the PUT directly to classController URL:

    NSString *_urlString = [NSString  stringWithFormat: @"https://serviceURL:449/api/auditorias"];


    Dont know if I should send it to root:
    NSString *_urlString = [NSString  stringWithFormat: @"https://serviceURL:449/"]; and append the controller URL in header or body, or maybe I'm forgetting some parameter in body.

    Here are all parameters I've been using in request:

    Authentication with Basic Authentication (works in GET):
     
    NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", user, password];
        NSString *authValue = [NSString stringWithFormat:@"Basic %@", AFBase64EncodedStringFromString(basicAuthCredentials)];
        [_request setValue:authValue forHTTPHeaderField:@"Authorization"];
        NSDictionary *_headers = [NSDictionary dictionaryWithObjectsAndKeys:@"application/json", @"accept", nil];
        [_request setAllHTTPHeaderFields:_headers];
     
    Other parameters:
     
        NSData *requestData = [NSData dataWithBytes:[jsonString UTF8String] length:[jsonString length]]; (jsonString is the output posted before)
         
        [_request setHTTPMethod:@"PUT"];
        [_request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        [_request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
        [_request setHTTPBody: requestData];

    Thank you for your interest.

  5. Hristo Marinov
    Admin
    Hristo Marinov avatar
    13 posts

    Posted 11 Jan 2013 Link to this post

    Hello Galobart,

    You are on the right direction - when the HttpStatusCode is set to NoContent in the response - no data is sent from the service. But to send data via the HttpResponseMessage, an overload of the Request.CreateResponse method should be use, in which for the second parameter is passed an object.
    For example see Line 12:
    01.public virtual HttpResponseMessage Put(WebService.Region entity)
    02.{
    03.    if (entity == null)
    04.    {
    05.        HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.BadRequest, "BadRequest");
    06.        throw new HttpResponseException(response);
    07.    }
    08.     
    09.    try
    10.    {
    11.        repository.Update(entity);
    12.        return Request.CreateResponse(HttpStatusCode.Accepted, entity);
    13.    }
    14.    catch
    15.    {
    16.        string response = "InternalServerError";
    17.        return Request.CreateResponse(HttpStatusCode.InternalServerError, response);
    18.    }
    19.}


    Here is a code snippet from a client application which invokes the service:
    HttpClient client = new HttpClient();
                 
    Region region = new Region()
    {
           RegionDescription = "TestDescription",
           RegionID = 2
    };
     
    HttpResponseMessage response = client.PutAsJsonAsync("http://localhost:49298/api/regions/", region).Result;
    string responseBody = await response.Content.ReadAsStringAsync();

    In this way you will receive data from the service along with the HttpStatusCode.

    Let us know whether the proposed solution helps.

    Kind regards,
    Hristo Marinov
    the Telerik team
    Q3'12 SP1 of OpenAccess ORM packs Multi-Table Entities mapping support. Check it out.
  6. Galobart
    Galobart avatar
    4 posts
    Member since:
    Mar 2010

    Posted 15 Jan 2013 Link to this post

    It was an ios code problem, and finally I have solved using a third party library.

    Thanks Hristo for your support.
Back to Top
DevCraft banner