LargeJsonResult in MVC return many values - c#

I have a controller which return many datas. then i got "Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property."
i have add my web.config using this. But the error is still occured.
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="2147483645" recursionLimit="100">
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
then I add new class LargeJsonResult like on this website http://brianreiter.org/2011/01/03/custom-jsonresult-class-for-asp-net-mvc-to-avoid-maxjsonlength-exceeded-exception/
it said like this in controller
return new LargeJsonResult() { Data = output, MaxJsonLength = int.MaxValue };
but how can I use that with many return data? below is my controller
public ActionResult LoadInitData()
{
try
{
Database db = new Database("CON001");
_employee = Helper.Common.GetEmployeeData(db);
EmployeeDAC dacEmployee = new EmployeeDAC(db);
Employee dataEmployee = dacEmployee.GetDataByComputerLogin(GetUser());
if (_employee.SBU == "FB")
{
BrandBudgetDAC dacBrandBudget = new BrandBudgetDAC(db);
List<BrandBudget> dataBrandBudget = dacBrandBudget.GetDataBrandFB();
PostBudgetDAC dacPostBudget = new PostBudgetDAC(db);
List<PostBudget> dataPostBudget = dacPostBudget.GetDataPostFB();
AreaDAC dacArea = new AreaDAC(db);
List<Area> dataArea = dacArea.GetData();
return Json(new { Employee = dataEmployee, BrandBudget = dataBrandBudget, PostBudget = dataPostBudget, Area = dataArea }, JsonRequestBehavior.AllowGet);
}
else
{
BrandBudgetDAC dacBrandBudget = new BrandBudgetDAC(db);
List<BrandBudget> dataBrandBudget = dacBrandBudget.GetData(_employee.SBU);
PostBudgetDAC dacPostBudget = new PostBudgetDAC(db);
List<PostBudget> dataPostBudget = dacPostBudget.GetData(_employee.SBU);
AreaDAC dacArea = new AreaDAC(db);
List<Area> dataArea = dacArea.GetData();
return Json(new { Employee = dataEmployee, BrandBudget = dataBrandBudget, PostBudget = dataPostBudget, Area = dataArea }, JsonRequestBehavior.AllowGet);
}
}
catch (Exception ex)
{
return Json(new { Error = ex.Message }, JsonRequestBehavior.AllowGet);
}
}

To reduce the payload, consider making 4 separate ajax calls, each to a different method that returns one of the 4 properties you need.
public ActionResult LoadInitEmployeeData()
{
Employee dataEmployee = ....
....
return Json(dataEmployee, JsonRequestBehavior.AllowGet)
}
public ActionResult LoadBrandBudgetData()
{
List<BrandBudget> dataBrandBudget = ....
return Json(dataBrandBudget, JsonRequestBehavior.AllowGet)
}
etc.

Related

Trying to get file response from ASP.NET Web API

I have migrated some methods from a MVC controller to a Web API controller and now I have this method:
[HttpPost]
[Route("api/Request/UploadImage")]
public IHttpActionResult UploadImage()
{
try
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var httpRequest = System.Web.HttpContext.Current.Request;
if (_inMemoryStore == null)
{
_inMemoryStore = new List<FileLocalStore>();
}
if (httpRequest.Files.Count > 0)
{
var postedFile = httpRequest.Files[0];
var uniqueFileName = Guid.NewGuid().ToString();
var fileStream = new MemoryStream();
postedFile.InputStream.CopyTo(fileStream);
_inMemoryStore.Add(new FileLocalStore() { Id = uniqueFileName, File = fileStream });
var fileStore = new ServiceRequestAttachmentViewModel
{
FileName = httpRequest.Form["FileName"].ToString(),
FileMIME = httpRequest.Form["FileMIME"].ToString(),
UniqueFileName = uniqueFileName,
Thumbnail = fileStream.GetBuffer().GetThumbnailImage(80, 80),
IsPrivate = Convert.ToBoolean(httpRequest.Form["IsPrivate"].ToString()),
IsAdded = true,
IsDeleted = false
};
var content = JsonConvert.SerializeObject(fileStore);
// return Ok(fileStore);
return Content(HttpStatusCode.OK,fileStore);
}
else
{
return Ok(new { Data = "" });
//return Request.CreateResponse(HttpStatusCode.Created, new
//{ Data = "" });
}
}
catch (Exception ex)
{
Log.Error($"Error uploading image {ex.Message} {ex.InnerException} {ex.StackTrace}");
return BadRequest(ex.Message);
//var response2 = Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message);
//return response2;
}
}
In the original MVC controller, it was easy to return the ContentResult after fileStore was serialized. I want to do the same thing here but I'm having issues. It keeps saying it exceeds the maximum bytes but the file was only 10k big.
Is there something else I need to set? the media type received is a multipart/form-data type. The thumbnail property is the issue as it has bytes of data.
This is being called using fileupload() method of jQuery.
You probably net to update the maxRequestLength & maxAllowedContentLength in web.config
From MSDN, the maximum default size is 4MB
Here's the setting for 1GB
<system.web>
<httpRuntime maxRequestLength="2097152" requestLengthDiskThreshold="2097152" executionTimeout="240"/>
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="2147483648" />
</requestFiltering>
</security>
</system.webServer>

While inserting data into the oracle database code automatically generate value 0 for id using MVC with entity framework

While inserting data into the Oracle database code automatically generate value 0 for id using MVC with entity framework.How to solve this.
public ActionResult AddNewNode(AddNode model)
{
try
{
if (ModelState.IsValid)
{
using (Nspira_DBContext entity = new Nspira_DBContext())
{
TBL_ACCESSRIGHTS hierarchyDetail = new TBL_ACCESSRIGHTS()
{
NAME = model.NodeName,
PID = model.ParentName,
};
entity.TBL_ACCESSRIGHTS.Add(hierarchyDetail);
entity.SaveChanges();
}
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
}
catch (Exception ex)
{
throw ex;
}
return Json(new { success = false }, JsonRequestBehavior.AllowGet);
}
My table has ID, NAME and PID column.While inserting query in the database means it generated the sequence number.While inserting data through code means It doesn't create the sequence.It fetches value as 0 automatically.How to solve this.
How to solve this.Please, anyone, help me.
if (ModelState.IsValid)
{
using (Nspira_DBContext entity = new Nspira_DBContext())
{
int objid = entity.TBL_ACCESSRIGHTS.Max(p => p.ID);
TBL_ACCESSRIGHTS hierarchyDetail = new TBL_ACCESSRIGHTS()
{
ID = objid + 1,
NAME = model.NodeName,
PID = model.ParentName,
};
entity.TBL_ACCESSRIGHTS.Add(hierarchyDetail);
entity.SaveChanges();
}
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
}
please try this

Controller action that receives any data in xml json or form-urlencoded

I have a requirement to create a controller action that can accept any data in XML, JSON or form-urlencoded. However, I couldn't make it work.
If my action has a Dictionary<string, object> parameter, it works for JSON and XML data, but not for form-urlencoded. If my action has a FormDataCollection parameter, it works for form-urlencoded but not for JSON and XML.
[HttpPost]
public HttpResponseMessage Default(FormDataCollection data /*Dictionary<string,object> data*/)
{
try
{
if (data == null)
return Request.CreateResponse(HttpStatusCode.BadRequest, new { ErrorMessage = "The request body is empty" });
//var collection = GetCollection(data); //used when data=Dictionary<string,object>
var collection = data.ReadAsNameValueCollection();
var agent = new ScriptingAgentClient();
var parameters = ServiceAgentParameters.From(collection);
var result = agent.Run(parameters);
if (result.Error)
return Request.CreateResponse(HttpStatusCode.BadRequest, new { ErrorMessage = result.ErrorMessage, Exception = result.Exception });
if (result.Data != null && result.Data.Count == 1) //result.Data is byte[]
{
//TODO: use the right Serializer
var resultString = Encoding.UTF8.GetString(result.Data[0]);
var serializer = new JavaScriptSerializer();
var dict = serializer.Deserialize<Dictionary<string, string>>(resultString);
return Request.CreateResponse(HttpStatusCode.OK, dict);
}
return Request.CreateResponse(HttpStatusCode.BadRequest, new { ErrorMessage = "Unknown error" });
}
catch (Exception ex)
{
Logger.Error("Error handling request", ex);
return Request.CreateResponse(HttpStatusCode.BadRequest, new { ErrorMessage = ex.Unwrap().Message });
}
}
ScriptingAgentClient will handle the data, whatever it may be.
If this isn't possible, how can I create two actions with same route where one will handle XML/JSON and another will handle form-urlencoded?
Note that I'm using .net40 and I can't change that. Noteworthy to mention that this webapi is a self-hosted api that will run in a windows service.
I was able to make it work reading the Request instead of letting WebApi figuring it out:
[HttpPost]
public HttpResponseMessage Default()
{
try
{
NameValueCollection collection = Request.Content.IsFormData() ?
Request.Content.ReadAsFormDataAsync().Result :
GetCollection(Request.Content.ReadAsAsync<IDictionary<string, object>>().Result);
var parameters = ServiceAgentParameters.From(collection);
var agent = new ScriptingAgentClient();
var response = agent.Run(parameters);
if (response.Error)
return Request.CreateResponse(HttpStatusCode.BadRequest, new { ErrorMessage = response.ErrorMessage, Exception = response.Exception });
if (response.Data != null && response.Data.Count == 1) //result.Data is List<byte[]>
{
//TODO: use the right Serializer
var resultString = Encoding.UTF8.GetString(result.Data[0]);
var serializer = new JavaScriptSerializer();
var dict = serializer.Deserialize<Dictionary<string, string>>(resultString);
return Request.CreateResponse(HttpStatusCode.OK, dict);
}
return Request.CreateResponse(HttpStatusCode.BadRequest, new { ErrorMessage = "Unknown error" });
}
catch (Exception ex)
{
Logger.Error("Error handling request", ex);
return Request.CreateResponse(HttpStatusCode.BadRequest, new { ErrorMessage = ex.Unwrap().Message });
}
}

Declare variable to return Json result (ASP.NET MVC4)

This is action from my controller
[HttpPost]
[AjaxAction]
public ActionResult Registration(RegisterUserModel registerUser)
{
var data;
if (ModelState.IsValid)
{
if (!IsUserExist(registerUser.Email))
{
var crypto = new SimpleCrypto.PBKDF2();
var encrpPass = crypto.Compute(registerUser.Password);
var newUser = _db.Users.Create();
newUser.Name = registerUser.Name;
newUser.Email = registerUser.Email;
newUser.Type = UserType.User.ToString();
newUser.Password = encrpPass;
newUser.PasswordSalt = crypto.Salt;
_db.Users.Add(newUser);
_db.SaveChanges();
data = new { status = "OK", message = "Success" };
}
else
{
data = new { status = "ERROR", message = "User already exists" };
}
}
else
{
data = new { status = "ERROR", message = "Data is incorrect" };
}
return Json(data, JsonRequestBehavior.AllowGet);
}
but I don't know how to initialize data variable in the right way, because I need to set different values in different cases. What is the right way to do that?
I usually use multiple return statements to avoid having to declare an object like
if(something){
return Json(new{status = "status 1", message = "message1"})
}
else{
return Json(new{status = "status 2", message = "message2"})
}
you can try this:
var data = new object();
Here is one of the options
[HttpPost]
[AjaxAction]
public ActionResult Registration(RegisterUserModel registerUser)
{
JsonResult data;
if (ModelState.IsValid)
{
if (!IsUserExist(registerUser.Email))
{
var crypto = new SimpleCrypto.PBKDF2();
var encrpPass = crypto.Compute(registerUser.Password);
var newUser = _db.Users.Create();
newUser.Name = registerUser.Name;
newUser.Email = registerUser.Email;
newUser.Type = UserType.User.ToString();
newUser.Password = encrpPass;
newUser.PasswordSalt = crypto.Salt;
_db.Users.Add(newUser);
_db.SaveChanges();
data = Json(new { status = "OK", message = "Success" }, JsonRequestBehavior.AllowGet);
}
else
{
data = Json(new { status = "ERROR", message = "User already exists"}, JsonRequestBehavior.AllowGet);
}
}
else
{
data = Json(new { status = "ERROR", message = "Data is incorrect" }, JsonRequestBehavior.AllowGet);
}
return data;
}
You can use the dynamic keyword.
dynamic data;

Unit Testing using Moq

This is a method under my controller which is used to create dummy keys to encrypt the data in the application and store the same in the amazon s3 bucket.
public JsonResult SaveMasterKeys(string MekText, int Thismek)
{
string folderName = string.Empty, fileName = string.Empty;
List<string> folderNameList = new List<string>();
folderNameList.Add("Guard1");
folderNameList.Add("Guard2");
try
{
if (Thismek == 1)
{
folderName = "Guard1";
fileName = "NewMek1.key";
}
else
{
folderName = "Guard2";
fileName = "NewMek2.key";
}
AWSS3File aws = new AWSS3File();
//aws.BucketExist(filePath);
//aws.CreateFile(MekText, filePath);
// Check Weather the Folder is exist or not
if (!aws.CheckFolderExist(folderName))
{
foreach (var item in folderNameList)
{
aws.CreateFolder(item);
if (item == "Guard1")
{
aws.CreateFileIntoS3((item == folderName ? MekText : ""), item, "NewMek1.key");
aws.CreateFileIntoS3("", item, "Mek1.key");
}
else
{
aws.CreateFileIntoS3((item == folderName ? MekText : ""), item, "NewMek2.key");
aws.CreateFileIntoS3("", item, "Mek2.key");
}
}
}
else
{
aws.CreateFileIntoS3(MekText, folderName, fileName);
}
ViewData["SaveMessage"] = "Saved successfully.";
}
catch (Exception ex)
{
XTP.Logger.LogCritical("XTP.Web.internaltools", ex.ToString());
ViewData["SaveMessage"] = "Keys not updated successfully.";
}
return Json(new { success = true, value = ViewData["SaveMessage"] }, JsonRequestBehavior.AllowGet);
}
And this is the TESTMETHOD I have written for the same
[TestMethod]
public void MockAlways()
{
var mock = new Mock<AccountController>();
JsonResult json = new JsonResult();
//new { success = true, value = ViewData["SaveMessage"] }, JsonRequestBehavior.AllowGet
json.Data = new { success = true, value = "sa" };
json.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
mock.Setup(x => x.SaveMasterKeys("ss", 1)).Returns(json);
var controller = new AccountController();
var result = controller.SaveMasterKeys("ss", 1) as JsonResult;
Assert.AreEqual(mock.Object.SaveMasterKeys("ssxs", 1), result.Data.ToString());
}
I am getting an invalid setup error. Is there a way to resolve this error?
I think that you misunderstood how to mock a controller's action. You are mocking it and then comparing it with the mocked controller. This is not a way to go(it is like checking whether true == true.
Basically this error means that Moq cannot override non-virtual member(it is self-explanatory). You should change method's signature to virtual to allow overriding it.
But - you shouldn't mock action like this. Instead you should mock its dependencies(services, contexts, gateways etc.) and check whether with known input values you can get expected results without mocking the action itself.

Categories