JsonResult method is not working/loading - c#

I am doing this tutorial.
In my controller class I have my
public JsonResult GetAllUser(){
List<database1> allUser = new List<database1>();
using (dbContext1 dc = new dbContext1 ())
{
allUser = dc.database1.ToList();
}
return new JsonResult()
{
Data = allUser,
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
MaxJsonLength = Int32.MaxValue
};
}
public JsonResult GetUserWithSerialNumber(string prefix){
List<database1> allUser = new List<database1>();
using (dbContext1 dc = new dbContext1())
{
allUser = dc.database1.Where(a => a.SerialNumber.Equals(prefix)).ToList();
}
return new JsonResult { Data = allUser, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
As of right now, GetAllUser() does not work while get GetUserWithSerialNumber() returns what it is suppose to. Originally GetAllUser() worked, then it gave me
"The length of the string exceeds the value set on the maxJsonLength property."
so I put "Int32.MaxValue" in the GetAllUser method and now when I run the webpage and click on the GetAllUser button it gives me
A script on this page may be busy, or it may have stopped responding. You can stop the script now, open the script in the debugger, or let the script continue.Script: http://localhost:54936/Scripts/jquery-1.10.2.js:7017
All my other methods work except the GetAllUser(). My cshtml and other code looks exactly like the on in the tutorial so I am not sure what I am doing wrong.

I found out the only reason I get the script message is because my database is huge. It's taking too long to go through all of the entries, put them in a list, and put it as an object.

Related

Fetching data from ElasticSeach NEST C#

So my goal is to use ElasticSearch, ES, as a log. To be more specific, i want to upload basically just a timestamp from when my application last ran. The uploading works fine but i cannot figure out how to fetch the data from the index. I've tried both using the Query and Aggregetion but in neither of cases have I managed to get some data. I get a response that says :
Valid NEST response built from a low level call on POST: /lastrun/lastrun/_search.
I have also tried searching for solutions but cannot manage to find anything that works for me. Can anyone help me fetch the data?
The index name is 'lastrun' and the class I upload to the index is called LastRun.
The Logger class
public static Boolean WriteLastRun()
{
var response = Elastic.Index(new LastRun { Date = DateTime.Now });
return response.IsValid ? true : false;
}
public static DateTime ReadLastRun()
{
var SearchResponse = Elastic.Search<LastRun>(s => s
.Query(q => q.MatchAll())
.Index("lastrun"));
Console.WriteLine(SearchResponse.Documents);
return new DateTime();
}
The LastRun class I upload to ES.
public class LastRun
{
public DateTime Date { get; set; }
}
Thanks!
EDIT
Settings for the Elastic:
var settings = new ConnectionSettings(new Uri("http://localhost:9200/")).DefaultIndex('lastrun');
ElasticClient Elastic = new ElasticClient(settings);
EDIT 2
I can verify that the same index is being uploaded to and searched by this code and by checking the same index in kibana.
var resolver = new IndexNameResolver(settings);
var index = resolver.Resolve<LastRun>();
Console.WriteLine(index); //prints 'lastrun'
Turns out that there wasn't a problem from the beginning. The Search method worked fine and I had the wrong ideĆ” of accessing the doc in the respons.
This is what is did, which was wrong:
Console.WriteLine(SearchResponse.Documents);
And here the right way to do it:
foreach (var item in SearchResponse.Documents)
{
Console.WriteLine(item.Date)
}

C# Rotativa ActionAsPDF no parameters passed

I'm trying to send parameters with ActionAsPdf using the Rotativa Library (1.6.4), unfortunately, the function is called but the parameter trainee in it is always null.
Here's my code:
List<T_Trainee> trainee= new List<T_Trainee>();
foreach (int f in foo)
{
T_Trainee t = new T_Trainee();
t.email = (string)Session["Mail"];
t.phone = (string)Session["Phone"];
trainee.Add(t);
}
//code to get the PDF
ActionAsPdf pdf = new ActionAsPdf("Index", trainee) { FileName = "Bulletin.pdf" };
Trainee var is a list of object T_Trainee not null -> seen in debug:
//function that return the PDF
public ActionResult Index(List<T_Trainee> trainee)
{
ViewModelFoo vmc = new ViewModelFoo();
vmc.trainee = trainee;
return View(vmc);
}
When the function is call in debug mode, I can clearly see that the parameter "trainee" is null but I still don't understand why.
Can anyone help me? Thanks!
ActionAsPdf seems to be a deprecated function in the last version of Rotativa.
I changed it by ViewAsPdf and now it works. The difference between the two function is that you have to send directly the view model inside the Index method call with ViewAsPdf.
Here's my code, I hope that it will help someone :
Code to call the index and send the viewModel
ViewModelFoo vmc = new ViewModelFoo();
List<T_Trainee> trainees= new List<T_Trainee>();
foreach (int f in foo)
{
T_Trainee t = new T_Trainee();
t.email = (string)Session["Mail"];
t.phone = (string)Session["Phone"];
trainees.Add(t);
}
vmc.trainees = trainees;
//code to get the PDF
ViewAsPdf pdf = new ViewAsPdf("Index", vmc)
{
FileName = "File.pdf",
PageSize = Rotativa.Options.Size.A4,
PageMargins = { Left = 0, Right = 0 }
};
Index that generate the view
public ActionResult Index()
{
return View(vmc);
}
Is foo populated?
Try sample code...
List trainee= new List();
trainee.Add(new T_Trainee {email = "sample#email.com", phone = "555-1212"});
Does that work?
You can also try to bind Action to a model
public ActionResult Index(ViewModelFoo vmc)
The second parameter of ActionAsPdf() is type of RouteValueDictionary, which is a dictionary of key and value. You passed in a custom type thereby it converts it to null. It should work if you pass a RouteValueDictionary instead.
ViewAsPdf() receives an object parameter and treats it as a model for view binding that's why it works.
You can have a look at its source code here:
https://github.com/webgio/Rotativa/blob/master/Rotativa/ActionAsPdf.cs

pass model from one action to another action in same controller

I am trying to pass my model List< Models.Statement > statementList from one action to another but i am receiving null value in the 2nd controller. Please suggest what is wrong here. Even tried with:
return RedirectToAction("WriteInTemplate", new { statementList = statementList });
Please help.
public ActionResult SendPdfStatement(string InvoiceNumber)
{
try
{
InvoiceNumber = InvoiceNumber.Trim();
ObjectParameter[] parameters = new ObjectParameter[1];
parameters[0] = new ObjectParameter("InvoiceNumber", InvoiceNumber);
List<Models.Statement> statementList = new List<Models.Statement>();
statementList = _db.ExecuteFunction<Models.Statement>("uspInvoiceStatement", parameters).ToList<Models.Statement>();
//WriteInTemplate(statementList);
return RedirectToAction("WriteInTemplate", statementList );
}
catch (Exception e)
{
InvoiceSearchTool.Models.udtExceptionTable exception = new udtExceptionTable();
exception.MethodName = "SendPdfStatement";
exception.Exception = e.ToString();
exception.Date = DateTime.Now;
DYNAMICS_EXTEntities db = new DYNAMICS_EXTEntities();
db.AddToudtExceptionTables(exception);
db.SaveChanges();
return View("Error");
}
}
public ActionResult WriteInTemplate(List<Models.Statement> statementList)
{
try
{
string invoiceNumber = statementList.FirstOrDefault().Invoice.ToString().Trim();
...................snip..........
return RedirectToAction("CreateMessageWithAttachment", "email", invoiceNumber);
}
catch (Exception e)
{
InvoiceSearchTool.Models.udtExceptionTable exception = new udtExceptionTable();
exception.MethodName = "WriteInTemplate";
exception.Exception = e.ToString();
exception.Date = DateTime.Now;
DYNAMICS_EXTEntities db = new DYNAMICS_EXTEntities();
db.AddToudtExceptionTables(exception);
db.SaveChanges();
return View("Error");
}
}
Please take a look here to pass your Model
you are not passing "statementList" , instead you are passing new { statementList= statementList} just pass the model and you should be fine .
return RedirectToAction("WriteInTemplate", statementList);
Answer by sino
RedirectToAction() writes a redirect command to the browser, making it start a brand new request to WriteInTemplate(). Your model object is therefore lost.
Is WriteInTemplate() an independent action which will sometimes be responsible for an entire request from a user or a partial request from a view? If not, you should just call it as a regular method instead of using RedirectToAction().
This is because you had spefified wrong route parameters.
while thinking about this.. did you check that the data are not null?
you are using
return RedirectToAction("WriteInTemplate", statementList );
instead you should use
return RedirectToAction("WriteInTemplate","controllerName", new{"statementList"=stetementList});
see reference here
The way you call the RedirectToAction() method may not be your issue.
For me, the solutions presented above did not work because the RedirectToAction() method builds a RouteValueDictionary by using the .ToString() value of each property in the model. This will only work if all the properties in the model are simple properties and it fails if any properties are complex objects, lists, collections, etc.
because this method does not use recursion.
If for example, a model called MymodelOrganization contained a property List Employees, then that property would result in a query string value of
....&Employees=System.Collections.Generic.List'1[System.String]
and binding would fail, and you would end up (as was my case) with ... null
I had this problem, so I created a copy of my model containing only the elements of the form, stripping my Lists and passed that inside RedirectToAction().
Once on the other action method, I was able to re-assemble my Lists and added them to my Model before calling the last return. Good luck. Here is the idea in my code:
[HttpPost]
public ActionResult ItemSubmissionForm(CombinedModelContent membervalues)
{ ...
ItemSubmissionsDBFields aFieldsList = membervalues.FieldsList; //Stripping other objects
return RedirectToAction("ItemSubmissionConfirm", aFieldsList);
}
[HttpGet]
public ActionResult ItemSubmissionConfirm(ItemSubmissionsDBFields aFieldsList)
{ ...
List<SomeArea> SomeAreaitems = new List<SomeArea>();
SomeAreaitems.Add ...
CombinedModelContent copymembervalues = new CombinedModelContent();
copymembervalues.SomeCodeLists = SomeAreaitems;
copymembervalues.FieldsList = aFieldsList;
return View("SomeConfirmPage", copymembervalues);

MVC Stream outputting to HTML div

Small problem here with an MVC app that I'm not sure how to figure out a way around.
Basically, I'm adding additional functionality to a system that was originally created by someone else (c#). For a reporting system, the results were only ever displayed on screen. Now I am building in the functionality to allow the user the ability to download their report as an Excel document.
So basically, I have a view that displays the date ranges, and some other search refinement options to the user. I have introduced a radio button that if selected will download the report as opposed to displaying it on screen.
Here are my three actions within the ReportController:
public ActionResult Index()
{
return View();
}
public ActionResult ProductReport(AdminReportRequest reportRequest, FormCollection formVariables)
{
AdminEngine re = new AdminEngine();
if (!reportRequest.Download)
{
AdminReport report = re.GetCompleteAdminReport(reportRequest);
return View(report);
}
Stream ExcelReport = re.GetExcelAdminReport(reportRequest);
TempData["excelReport"] = ExcelReport;
return RedirectToAction("ExcelProductReport");
}
public FileResult ExcelReport()
{
var ExcelReport = TempData["excelReport"] as Stream;
return new FileStreamResult(ExcelReport, "application/ms-excel")
{
FileDownloadName = "Report" + DateTime.Now.ToString("MMMM d, yyy") + ".xls"
};
}
I've debugged through the AdminEngine, and everything looks fine. However, in the ExcelReport action, when it comes to returning the file - it doesn't. What I see is a lot of characters on screen (in the 'panelReport' div - see below), mixed in with what would be the data in the excel file.
I think I have established that the reason it is being displayed on screen is as a result of some code
that was written in the Index view:
<% using (Ajax.BeginForm("ProductReport", "Report", null,
new AjaxOptions
{
UpdateTargetId = "panelReport",
InsertionMode = InsertionMode.Replace,
OnSuccess = "pageLoaded",
OnBegin = "pageLoading",
OnFailure = "pageFailed",
LoadingElementId = ""
},
new { id = "SearchForm" })) %>
As you can see, the Ajax.BeginForm statement states that it should update to the panelReport div - which is what it's doing (through the Product Report partial view). While this is perfect for when the reports need to be displayed on screen, it is obviously not going to work with an excel file.
Is there a way of working around this issue without changing the existing code too much?
Here is the class where I do the workings for the excel file in case it's required to shed light on the situation:
Report Class:
public Stream GetExcelAdminReport(AdminReportRequest reportRequest)
{
AdminReport report = new AdminReport();
string dateRange = null;
List<ProductSale> productSales = GetSortedListOfProducts(reportRequest, out dateRange);
report.DateRange = dateRange;
if (productSales.Count > 0)
{
report.HasData = true;
CustomisedSalesReport CustSalesRep = new CustomisedSalesReport();
Stream SalesReport = CustSalesRep.GenerateCustomisedSalesFile(productSales);
return SalesReport;
}
}
Workings Class:
public class CustomisedSalesReport
{
public Stream GenerateCustomisedSalesFile(List<ProductSale> productSales)
{
MemoryStream ms = new MemoryStream();
HSSFWorkbook templateWorkbook = new HSSFWorkbook();
HSSFSheet sheet = templateWorkbook.CreateSheet("Sales Report");
//Workings
templateWorkbook.Write(ms);
ms.Position = 0;
return ms;
}
}
The problem is pretty obvious that you are using an Ajax Form to download a file. On top you are using the built-in Microsoft Ajax libraries, which seem to be not intelligent enough.
I can provide 2 solutions:
The easiest solution (which I have used in the past) is that instead of streaming a file yourself, create an excel file and save it on the server and then send the download link to the user. It won't require a lot of change to the code.
You could handle the OnSubmit event of the AjaxForm, see if you it's a file to download. If yes, then make a full postback request (using $.post()). This way the browser will automatically pop-up the dialog asking for where to download.
Hope it makes sense.

Persist data using JSON

I'm tryping to use JSON to update records in a database without a postback and I'm having trouble implementing it. This is my first time doing this so I would appreciate being pointed in the right direction.
(Explanation, irrelevant to my question: I am displaying a list of items that are sortable using a jquery plugin. The text of the items can be edited too. When people click submit I want their records to be updated. Functionality will be very similar to this.).
This javascript function creates an array of the objects. I just don't know what to do with them afterwards. It is called by the button's onClick event.
function SaveLinks() {
var list = document.getElementById('sortable1');
var links = [];
for (var i = 0; i < list.childNodes.length; i++) {
var link = {};
link.id = list.childNodes[i].childNodes[0].innerText;
link.title = list.childNodes[i].childNodes[1].innerText;
link.description = list.childNodes[i].childNodes[2].innerText;
link.url = list.childNodes[i].childNodes[3].innerText;
links.push(link);
}
//This is where I don't know what to do with my array.
}
I am trying to get this to call an update method that will persist the information to the database. Here is my codebehind function that will be called from the javascript.
public void SaveList(object o )
{
//cast and process, I assume
}
Any help is appreciated!
I have recently done this. I'm using MVC though it shouldn't be too different.
It's not vital but I find it helpful to create the contracts in JS on the client side and in C# on the server side so you can be sure of your interface.
Here's a bit of sample Javascript (with the jQuery library):
var item = new Item();
item.id = 1;
item.name = 2;
$.post("Item/Save", $.toJSON(item), function(data, testStatus) {
/*User can be notified that the item was saved successfully*/
window.location.reload();
}, "text");
In the above case I am expecting text back from the server but this can be XML, HTML or more JSON.
The server code is something like this:
public ActionResult Save()
{
string json = Request.Form[0];
var serializer = new DataContractJsonSerializer(typeof(JsonItem));
var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(json));
JsonItem item = (JsonItem)serializer.ReadObject(memoryStream);
memoryStream.Close();
SaveItem(item);
return Content("success");
}
Hope this makes sense.
You don't use CodeBehind for this, you use a new action.
Your action will take an argument which can be materialized from your posted data (which, in your case, is a JavaScript object, not JSON). So you'll need a type like:
public class Link
{
public int? Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Url { get; set; }
}
Note the nullable int. If you have non-nullable types in your edit models, binding will fail if the user does not submit a value for that property. Using nullable types allows you to detect the null in your controller and give the user an informative message instead of just returning null for the whole model.
Now you add an action:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult DoStuff(IEnumerable<Link> saveList)
{
Repository.SaveLinks(saveList);
return Json(true);
}
Change your JS object to a form that MVC's DefaultModelBinder will understand:
var links = {};
for (var i = 0; i < list.childNodes.length; i++) {
links["id[" + i + "]"] = list.childNodes[i].childNodes[0].innerText;
links["title[" + i + "]"] = list.childNodes[i].childNodes[1].innerText;
links["description[" + i + "]"] = list.childNodes[i].childNodes[2].innerText;
links["url[" + i + "]"] = list.childNodes[i].childNodes[3].innerText;
}
Finally, call the action in your JS:
//This is where I don't know what to do with my array. Now you do!
// presumes jQuery -- this is much easier with jQuery
$.post("/path/to/DoStuff", links, function() {
// success!
},
'json');
Unfortunately, JavaScript does not have a built-in function for serializing a structure to JSON. So if you want to POST some JSON in an Ajax query, you'll either have to munge the string yourself or use a third-party serializer. (jQuery has a a plugin or two that does it, for example.)
That said, you usually don't need to send JSON to the HTTP server to process it. You can simply use an Ajax POST request and encode the form the usual way (application/x-www-form-urlencoded).
You can't send structured data like nested arrays this way, but you might be able to get away with naming the fields in your links structure with a counter. (links.id_1, links.id_2, etc.)
If you do that, then with something like jQuery it's as simple as
jQuery.post( '/foo/yourapp', links, function() { alert 'posted stuff' } );
Then you would have to restructure the data on the server side.

Categories

Resources