2011-10-28 27 views
5

Estoy publicando datos JSON en un servidor ASP.NET MVC2. Estoy publicando cadenas JSON grandes (que incorporan una secuencia de archivos codificada en base64, leída desde el sistema de archivos local). La llamada jQuery ajax funciona bien hasta tamaños de archivo de alrededor de 2.5Mb. Una vez por encima de este tamaño, la llamada ajax falla (nunca llega al controlador). No puedo detectar exactamente cuál es el error: parece que no llena las variables de error.La publicación jQuery .ajax falla con el objeto JSON grande

La llamada ajax es como sigue:

$.ajax({ 
      type: "POST", 
      dataType: 'json', 
      timeout: 10000, 
      url: "/Molecule/SaveMolecule", 
      data: { jsonpost: postdata, moleculetype: _moleculeType, moleculefilestream: _moleculefilestream, changedproducts: stringifiedChangedProducts }, // NOTE the moleculeType being added here 
      success: function (data) { 
       if (data.rc == "success") { 
        $.log('ServerSuccess:' + data.message); 

        molecule_updateLocalInstance(); 

        _bMoleculeIsDirty = false; 
        if (bReturnToMoleculeList != null && bReturnToMoleculeList == true) { 
         navigator_Go('/Molecule/Index/' + _moleculeType); 
        } 
        else { 
         _saveMoleculeButtonFader = setTimeout(function() { 

          $('#profilesave-container').delay(500).html('<img src="/content/images/tick.png" width="32px" height="32px" /><label>' + _moleculeSingularTerm + ' was saved</label>').fadeIn(500); 

          _saveMoleculeButtonFader = setTimeout(function() { $('#profilesave-container').fadeOut(1000); }, 2000); 

         }, 500); 
        } 

       } else { 
        $.log('ServerUnhappy:' + data.message); 
        RemoveMoleculeExitDialog(); 
       } 
      } 
      , error: function (jqXHR, textStatus, errorThrown) { 
       alert('Save failed, check console for error message:' +textStatus+' '+ errorThrown); 
       MarkMoleculeAsDirty(); 
       $.log('Molecule Save Error:' + helper_objectToString(textStatus+' '+errorThrown)); 
      } 
     }); 

donde _moleculefilestream es la gran corriente codificado en base 64.

Mi web.config incluye lo siguiente:

<system.web.extensions> 
    <scripting> 
     <webServices> 
     <jsonSerialization maxJsonLength="50000000"> 
     </jsonSerialization> 
     </webServices> 
    </scripting> 
    </system.web.extensions> 

Alguien tiene alguna idea brillante?

Respuesta

1

¿Has intentado ajustar el tiempo de espera? 10 segundos podrían ser suficientes para 2.5Mb pero no más.

+0

Gracias por la sugerencia de Erick: estoy probando esto localmente, por lo que 10s es suficiente para archivos grandes, pero tomo su punto para el entorno en vivo y aumentará el tiempo de espera en consecuencia. – Journeyman

1

ACTUALIZACIÓN

El elemento spnet:MaxJsonDeserializerMembers hay que añadir a la sección <appSettings> de su archivo web.config , el establecimiento de que es el equivalente del valor máximo de un tipo de datos Int32.

<configuration> 
    <appSettings> 
    <add key="aspnet:MaxJsonDeserializerMembers" value="2147483647" /> 
    </appSettings> 
</configuration> 

En esta página del documentation oficial, usted será capaz de encontrar toda la información acerca de los elementos, así como su uso.

Nota: En la sección de la documentación oficial, se recomienda no ajustar el valor máximo, ya que representa un riesgo para la seguridad. Idealmente, debe verificar el número de elementos que desea deserializar e intentar estimar en función del tamaño máximo de json que esté utilizando.

posterior

originales por @Flxtr: Here

VIEJO

Si desea cargar un archivo, ¿por qué no tratar de usar FormData

Por ejemplo:

function getDataForm() { 

    var data = new FormData(); 

    var files = fileUploader.get(0).files; 
    if (files.length > 0) { 
     data.append("File", files[0]); 
    } 
    data.append("ImagePath", ""); 

    data.append("Id", ImageId); 
    data.append("Name", txtName.val().trim()); 
    data.append("Description", txtDescription.val().trim()); 

    return data; 
} 

function save(data) { 
    $.ajax({ 
     type: "POST", 
     url: "/Files/SaveImage", 
     contentType: false, 
     processData: false, 
     data: data, 
     success: function (response) { 

      if (response.success) { 
       $.showMessage(messages.NAME, messages.SUCCESS, "success"); 
       closeForm(); 
       Files.ImageList.gridImages.ajax.reload(); 
      } 
      else { 
       $.showMessage(messages.NAME, response.message, "error"); 
      }; 

      btnSave.button('reset'); 
     }, 
     error: function (request, status, exception) { 
      $.showMessage(messages.NAME, exception, "error"); 
      btnSave.button('reset'); 
     } 
    }); 
}; 

Entonces , en el lado del servidor, cambie la longitud de la solicitud en la configuración web:

<httpRuntime targetFramework="4.6.1" maxRequestLength="65536"/> 

Por ejemplo:

<system.web> 
    <compilation debug="true" targetFramework="4.6.1" /> 
    <httpRuntime targetFramework="4.6.1" maxRequestLength="65536"/> 
    <customErrors mode="RemoteOnly"> 
     <error statusCode="401" redirect="/Error/401" /> 
     ... 
     <error statusCode="411" redirect="/Error/411" /> 
    </customErrors> 
    </system.web> 

Además, cambiar el parámetro processData-false en la solicitud Ajax:

$.ajax({ 
    url: "/Security/SavePermissions", 
    type: "POST", 
    processData: false, 
    contentType: "application/json; charset=utf-8", 
    data: JSON.stringify(pStrPermissions), 
    success: function (response) { 
     if (response.success) { 
      panel.showAlert("Permisos", "Se han actualizado correctamente los permisos.", "success"); 
      resetForm(); 
     } 
     else { 
      $.showMessage("Permisos", response.message, "error"); 
     }; 
    }, 
    error: function (request, status, exception) { 
     $.showMessage("Permisos", exception, "error"); 
    } 
}); 

Estas son sólo sugerencias. Lo único que realmente funcionó para mí fue serializar la lista y deserializarla en el servidor.

Por ejemplo, en el lado del cliente:

function savePermissions(pLstObjPermissions) { 
    $.ajax({ 
     url: "/Security/SavePermissions", 
     type: "POST", 
     dataType: "json", 
     contentType: "application/json; charset=utf-8", 
     data: JSON.stringify({ pStrPermissions: JSON.stringify(pLstObjPermissions)}) , 
     success: function (response) { 
      if (response.success) { 
       panel.showAlert("Permisos", "Se han actualizado correctamente los permisos.", "success"); 
       resetForm(); 
      } 
      else { 
       $.showMessage("Permisos", response.message, "error"); 
      }; 
     }, 
     error: function (request, status, exception) { 
      $.showMessage("Permisos", exception, "error"); 
     } 
    }); 
}; 

En el lado del servidor:

public ActionResult SavePermissions(string pStrPermissions) 
{ 
    var lLstObjResult = new Dictionary<string, object>(); 

    try 
    { 
     SecurityFactory.GetPermissionService().UpdateList(JsonConvert.DeserializeObject<IList<Permission>>(pStrPemissions)); 
     lLstObjResult.Add(MESSAGE, "Registro guardado exitosamente"); 
     lLstObjResult.Add(SUCCESS, true); 
    } 
    catch (Exception e) 
    { 
     lLstObjResult.Add(MESSAGE, e.Message); 
     lLstObjResult.Add(SUCCESS, false); 
    } 

    return Json(lLstObjResult, JsonRequestBehavior.AllowGet); 
} 

Sé que esta no es la mejor manera, pero funciona hasta que venga algo mejor.

Si tiene una mejor manera de resolver este problema, por favor compártalo.

Cuestiones relacionadas