Download File From MVC - javascript

I need a way to pass a list of strings when a user clicks an icon from angular/script and send it to an MVC controller in .NET. This list does what it needs to then is supposed to download a file in my browser. I have learned that I cannot do this via AJAX and/or it get pretty messy.
Edit: the list of strings refers to a list of file ids that I am retrieving, then zipping up into one file, which is to be downloaded. I do not want to store this zipped file anywhere permanently.
I am open to ideas!
$http.post('document/downloadfiles', data).success(function () {/*success callback*/ });
[HttpPost]
public ActionResult DownloadFiles(List<string> fileUniqueIdentifiers)
{
var file = _service.ArchiveAndDownloadDocuments(fileUniqueIdentifiers);
file.Position = 0;
return new FileStreamResult(file, "application/force-download");
}

Ok, third-time lucky I guess?
(I think this'll be my last implementation sorry Jim - you'll have to work the rest out for yourself, I think I've given you more than enough free pointers for now... if you want more you can contact me and I'll charge you to write it! :P).
This version uses a cookie-based interchange, accepts the input strings (assuming they are filenames) from the javascript, stores these in the instance class along with the token as key, then assembles the ZipFile in-memory (without writing to disk), and then returns the zipfile as a Content Result. For efficiency you could remove the actual token checks against the GUID list and just check against the key in the file list. Obviously you probably won't want the filenames hard-coded in that javascript as I've done, but you can work that part out for yourself.
Hint: Create a database table with identifier/filepath pairs and use the identifiers to lookup the individual file paths after the request is sent to the server...
View Part (I added mine to index.cshtml):
<script type="text/javascript">
function sendStringandGetFiles() {
var files = ['c:\\temp\\afile.txt', 'c:\\temp\\afile2.txt', 'c:\\temp\\afile3.txt'];
$.ajax({
type: "POST",
url: "/Home/GetFile",
contentType: 'application/json',
data: JSON.stringify(files),
success: function (result) {
//alert("Yes This worked! - " + result);
window.location = "/Home/GetFile";
}
});
}
</script>
<h5>Just something to click</h5>
<button onclick="sendStringandGetFiles()">Send String and Get Files</button>
Then Controller Part (I used HomeController.cs)
[AcceptVerbs(HttpVerbs.Post)]
public string GetFile(string[] strings)
{
Guid token = Guid.NewGuid();
InMemoryInstances instance = InMemoryInstances.Instance;
instance.addToken(token.ToString());
instance.addFiles(token.ToString(), strings);
HttpCookie cookie = new HttpCookie("CookieToken");
cookie.Value = token.ToString();
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
return token.ToString();
}
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetFile()
{
InMemoryInstances instance = InMemoryInstances.Instance;
if (this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains("CookieToken"))
{
HttpCookie cookie = this.ControllerContext.HttpContext.Request.Cookies["CookieToken"];
if (instance.checkToken(cookie.Value))
{
cookie.Expires = DateTime.Now.AddDays(-1);
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
MemoryStream ms = new MemoryStream();
string[] filenames = instance.getFiles(cookie.Value);
using (ZipArchive zs = new ZipArchive(ms,ZipArchiveMode.Create, true))
{
for (int i=0;i < filenames.Length; i++)
zs.CreateEntryFromFile(filenames[i], Path.GetFileName(filenames[i]));
}
FileContentResult resultContent = new FileContentResult(ms.ToArray(),"application/zip");
instance.removeFiles(cookie.Value);
resultContent.FileDownloadName = "ARandomlyGeneratedFileNameHere.zip";
return resultContent;
} else
{
return View("Index");
}
}
else
{
return View("Index");
}
}
InMemoryInstances Class:
public class InMemoryInstances
{
private static volatile InMemoryInstances instance;
private static object syncRoot = new Object();
private List<Guid> activeTokens;
private NameValueCollection filesByKeyCollection;
private InMemoryInstances()
{
activeTokens = new List<Guid>();
filesByKeyCollection = new NameValueCollection();
}
public static InMemoryInstances Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new InMemoryInstances();
}
}
return instance;
}
}
public bool checkToken(string token)
{
return activeTokens.Contains(new Guid(token));
}
public string[] getFiles(string token)
{
return filesByKeyCollection.GetValues(token);
}
public bool addFiles(string token, string[] files)
{
for (int i = 0; i < files.Length; i++)
filesByKeyCollection.Add(token, files[i]);
return true;
}
public bool addToken(string token)
{
activeTokens.Add(new Guid(token));
return true;
}
public bool removeFiles(string token)
{
filesByKeyCollection.Remove(token);
return true;
}
public bool removeToken(string token)
{
return activeTokens.Remove(new Guid(token));
}
}
Hope this helps!

I normally wouldn't go to this length of effort to help, but I'm home sick and feel like writing some code, so here's an implementation of what I think you're asking for. Here I'm using token exchange to track the file interchange for a specific user storing the data in a singleton instance, you could use another method (e.g. database token storage) if you wanted...
View Part (I added mine to index.cshtml):
<script type="text/javascript">
function sendStringandGetFiles() {
var strings = ['One String', 'Two String', 'Three String'];
$.ajax({
type: "POST",
url: "/Home/GetFile",
contentType: 'application/json',
data: JSON.stringify(strings),
success: function (result) {
//alert("Yes This worked! - " + result);
window.location = "/Home/GetFile?token=" + result;
}
});
}
</script>
<h5>Just something to click</h5>
<button onclick="sendStringandGetFiles()">Send String and Get Files</button>
Then, Controller part (I used HomeController.cs):
[AcceptVerbs(HttpVerbs.Post)]
public string GetFile(string[] strings)
{
for (int i = 0; i < strings.Length; i++)
{
// Do some stuff with string array here.
}
Guid token = Guid.NewGuid();
InMemoryInstances instance = InMemoryInstances.Instance;
instance.addToken(token.ToString());
return token.ToString();
}
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetFile(string token)
{
string filename = #"c:\temp\afile.txt";
InMemoryInstances instance = InMemoryInstances.Instance;
if (instance.checkToken(token))
{
instance.removeToken(token);
FileStreamResult resultStream = new FileStreamResult(new FileStream(filename, FileMode.Open, FileAccess.Read), "txt/plain");
resultStream.FileDownloadName = Path.GetFileName(filename);
return resultStream;
}
else
{
return View("Index");
}
}
InMemoryInstances Class:
public class InMemoryInstances
{
private static volatile InMemoryInstances instance;
private static object syncRoot = new Object();
private List<Guid> activeTokens;
private InMemoryInstances()
{
activeTokens = new List<Guid>();
}
public static InMemoryInstances Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new InMemoryInstances();
}
}
return instance;
}
}
public bool checkToken(string token)
{
return activeTokens.Contains(new Guid(token));
}
public bool addToken(string token)
{
activeTokens.Add(new Guid(token));
return true;
}
public bool removeToken(string token)
{
return activeTokens.Remove(new Guid(token));
}
}
Hope this helps!

I also wrote yet another implementation which uses cookies to perform the same operation (incase you wanted to store the information client-side instead of using a query-string, yes, I'm slightly bored)...
View Part (I added mine to index.cshtml):
<script type="text/javascript">
function sendStringandGetFiles() {
var strings = ['One String', 'Two String', 'Three String'];
$.ajax({
type: "POST",
url: "/Home/GetFile",
contentType: 'application/json',
data: JSON.stringify(strings),
success: function (result) {
//alert("Yes This worked! - " + result);
window.location = "/Home/GetFile?token=" + result;
}
});
}
</script>
<h5>Just something to click</h5>
<button onclick="sendStringandGetFiles()">Send String and Get Files</button>
Then Controller Part (I used HomeController.cs)
[AcceptVerbs(HttpVerbs.Post)]
public string GetFile(string[] strings)
{
for (int i = 0; i < strings.Length; i++)
{
// Do some stuff with string array here.
}
Guid token = Guid.NewGuid();
InMemoryInstances instance = InMemoryInstances.Instance;
instance.addToken(token.ToString());
HttpCookie cookie = new HttpCookie("CookieToken");
cookie.Value = token.ToString();
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
return token.ToString();
}
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult GetFile()
{
string filename = #"c:\temp\afile.txt";
InMemoryInstances instance = InMemoryInstances.Instance;
if (this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains("CookieToken"))
{
HttpCookie cookie = this.ControllerContext.HttpContext.Request.Cookies["CookieToken"];
if (instance.checkToken(cookie.Value))
{
cookie.Expires = DateTime.Now.AddDays(-1);
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
FileStreamResult resultStream = new FileStreamResult(new FileStream(filename, FileMode.Open, FileAccess.Read), "txt/plain");
resultStream.FileDownloadName = Path.GetFileName(filename);
return resultStream;
} else
{
return View("Index");
}
}
else
{
return View("Index");
}
}
InMemoryInstances Class:
public class InMemoryInstances
{
private static volatile InMemoryInstances instance;
private static object syncRoot = new Object();
private List<Guid> activeTokens;
private InMemoryInstances()
{
activeTokens = new List<Guid>();
}
public static InMemoryInstances Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new InMemoryInstances();
}
}
return instance;
}
}
public bool checkToken(string token)
{
return activeTokens.Contains(new Guid(token));
}
public bool addToken(string token)
{
activeTokens.Add(new Guid(token));
return true;
}
public bool removeToken(string token)
{
return activeTokens.Remove(new Guid(token));
}
}
Maybe that is better if you want to hide the token interchange from the browser address bar?

Related

How to fix sending jsp page with a ajax call in Spring Boot? [duplicate]

I am trying to make an ajax request that sends a value to my spring boot. However, once I incorporate the ajax call and it successfully passes the value to java it does not view the jsp page. I believe the issue is from the method itself, but I am not entirely sure. Again I have the values being passed, but whenever I use ModelAndView or Model it seems to not change the page accordingly.
JSP:
<script>
var chaptersTest = ${ chapters };
var totalChapters = chaptersTest.length;
var codeBlock;
for (var i = 0; i < totalChapters; i++) {
codeBlock =
'<div class="col-md-4">' +
' <a class="chapter_link" data-link="' + chaptersTest[i] + '" style="text-decoration: none; color: white"><div class="box warning">' +
' <h3>' + chaptersTest[i] + '</h3>' +
' </div></a></div>';
$("#chapterArea").append(codeBlock);
}
//clicked links
$('.chapter_link').click(function () {
console.log("YoUR fUNCtION IS cLICKED");
doSomething();
});
function doSomething() {
var search2 = {
"chapter": "riley"
}
$.ajax({
type: "POST",
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: "/ajax",
data: JSON.stringify(search2),
success: function (result) {
console.log("It somewhat worked");
}
});
}
</script>
Java:
#RequestMapping(value = "/ajax", method = RequestMethod.POST)
public #ResponseBody String sectionView(#RequestBody BEntity benny, HttpServletRequest request) {
String temp = benny.getChapter();
ModelAndView secView = new ModelAndView();
try {
secView.setViewName("viewsections.jsp");
//It is not sending the jsp to change the page
} catch (Exception e) {
secView.setViewName("error.jsp");
}
System.out.println("Test 1");
return secView;
}
Object:
public class BEntity {
private String search;
private String chapter;
private String section;
public String getSection() {
return section;
}
public String getChapter() {
return chapter;
}
public String getSearch() {
return search;
}
#Override
public String toString() {
return "This was searched: " + search;
}
In your controller,remove #ResponseBody annotation and change the return type to ModelAndView. Change dataType to html in your ajax code.
If you have not configured view properly then, in your application.properties set the prefix and suffix as:
spring.mvc.view.prefix: /views/
spring.mvc.view.suffix: .jsp
spring.mvc.view.prefix is the path of the folder where your jsp files reside.
#RequestMapping(value = "/ajax", method = RequestMethod.POST)
public ModelAndView sectionView(#RequestBody BEntity benny, HttpServletRequest request) {
String temp = benny.getChapter();
ModelAndView secView = new ModelAndView();
try {
secView.setViewName("viewsections");
//It is not sending the jsp to change the page
} catch (Exception e) {
secView.setViewName("error");
}
System.out.println("Test 1");
return secView;
}

.net core Razor pages with JQuery AJAX

I am trying to call a Razor Page Handler using JQuery AJAX. Here is the sample code.
<script type="text/javascript">
$(document).ready(function () {
$("#SectionId").change(function () {
var options = {};
options.url = $(location).attr('href') + "/?SectionId=" + $("#SectionId").val() + "?handler=SelectByID";
options.type = "GET";
options.dataType = "json";
options.success = function (data) {
};
options.error = function () {
$("#msg").html("Error while making Ajax call!" + options.error.val);
};
$.ajax(options);
});
});
</script>
Razor Page cs code:
public class CreateModel : PageModel
{
private readonly ApplicationDbContext _context;
private readonly UserManager<ApplicationUser> _userManager;
private Task<ApplicationUser> GetCurrentUserAsync() => _userManager.GetUserAsync(HttpContext.User);
[BindProperty]
public FileRecord FileRecord { get; set; }
public List<SelectListItem> UserList { get; set; }
public string SelectedSectionId { get; set; }
public CreateModel(ApplicationDbContext context, UserManager<ApplicationUser> userManager)
{
_context = context;
_userManager = userManager;
}
public IActionResult OnGetSelectByID(string SectionId)
{
return null;
}
public async Task<IActionResult> OnGetAsync()
{
//Prepare UserList
UserList = new List<SelectListItem>();
List<ApplicationUser> Users = await _context.Users.ToListAsync();
foreach (var item in Users)
{
string role = Enum.GetName(typeof(EmRoles), EmRoles.NormalUser);
if (await _userManager.IsInRoleAsync(item, role) && item.IsEnabled)
{
UserList.Add(new SelectListItem()
{
Text = item.FullName,
Value = item.Id
});
}
}
//Sections
ViewData["Sections"] = new SelectList(_context.Sections, "Id", "Name");
//FileNOs
ViewData["Files"] = new SelectList(_context.FileRegisters, "Id", "FileNo");
//ViewData["ReceiverUserId"] = new SelectList(_context.Users, "Id", "Id");
//ViewData["SenderUserId"] = new SelectList(_context.Users, "Id", "Id");
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
//Two File Records have to be created. One For Sender & One for receiver.
FileRecord SenderRecord = new FileRecord
{
//create unique file id
//FileId = Guid.NewGuid().ToString(),
OutDate = DateTime.Now,
};
FileRecord ReceiverRecord = new FileRecord
{
//create unique file id
//FileId = SenderRecord.FileId,
InDate = SenderRecord.OutDate,
};
//Current logged-in user
var user = await GetCurrentUserAsync();
SenderRecord.OwnerUserId = user.Id;
//Receiver
ReceiverRecord.OwnerUserId = FileRecord.ReceiverUserId;
ReceiverRecord.SenderUserId = SenderRecord.OwnerUserId;
//Sender Record
if (await TryUpdateModelAsync<FileRecord>(SenderRecord, "FileRecord", f => f.FileId, f => f.Remarks, f => f.Gist, f => f.ReceiverUserId))
{
//Receiver Record
if (await TryUpdateModelAsync<FileRecord>(ReceiverRecord, "FileRecord", f => f.FileId, f => f.Gist))
{
_context.FileRecords.Add(SenderRecord);
_context.FileRecords.Add(ReceiverRecord);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
}
//If it reaches here. that means some error occurred.
return null;
}
}
The Issue is am not getting a call to Razor Page Handler defined above. If i skip the SectionId parameter passed-in & call only the handler. it is working fine. but it is not working when parameter is sent to the handler, default OnGet() is being called.
Help plz.
You don't need to append your handler parameter
options.url = $(location).attr('href') + "/?SectionId=" + $("#SectionId").val();
You also need to decorate the method with the HttpGet attribute
[HttpGet("GetSelectByID")]
public IActionResult OnGetSelectByID(string SectionId)
{
return null;
}
Then your URL to call this method needs to be
http://localhost:xxxx/FileMovement/Create/GetSelectByID?SectionId=yyy
When you have more than one GET defined on a controller you must tag the additional GET methods with the HttpGet attribute and add a string to define the name of that method.
Finally i was able to solve the issue.
<script type="text/javascript">
$(document).ready(function () {
$("#SectionId").change(function () {
var options = {};
options.url = $(location).attr('href') + "?handler=SelectByID" + "&SectionId=" + $("#SectionId").val();;
options.type = "GET";
options.dataType = "json";
options.success = function (data) {
};
options.error = function (data) {
$("#msg").html("Error while making Ajax call!" + data.error.val);
};
$.ajax(options);
});
});
Everything was right except i have to use "&" in "&SectionId="

Bad request errror between spring boot and angularjs by a post request

I have two small projects, backend spring-boot side is responsible for providing the data, and angularjs frontend part is just displaying that data. I am trying to post a json from angular side and spring-boot side consumes and sends a respond.
This is horse racing data in json; "jokey" means rider and contains rider information:
var list = {"horses": [{"horseId":45942,"horseName":"Decolte","raceId":8449,"kilo":61.0,"jokey":{"name":"AYETULLAH DEMİR","raceNumber":41,"first":1,"second":4,"third":0,"fourth":1},"ekuriId":0},
{"horseId":27520,"horseName":"Busıness Man","raceId":8449,"kilo":57.0,"jokey":{"name":"CİVAN ÖZŞAHİN","raceNumber":190,"first":7,"second":15,"third":18,"fourth":12},"ekuriId":0},
{"horseId":55856,"horseName":"Erselçuk","raceId":8449,"kilo":57.0,"jokey":{"name":"NAİL EREN","raceNumber":64,"first":2,"second":0,"third":4,"fourth":2},"ekuriId":0},
{"horseId":52940,"horseName":"Haşim Ağa","raceId":8449,"kilo":57.0,"jokey":{"name":"DOĞUKAN AYDOĞAN","raceNumber":380,"first":11,"second":18,"third":10,"fourth":24},"ekuriId":0},
{"horseId":53431,"horseName":"İhtiyar","raceId":8449,"kilo":57.0,"jokey":{"name":"CÜNEYİT GÖKÇE","raceNumber":598,"first":32,"second":52,"third":64,"fourth":65},"ekuriId":0},
{"horseId":51778,"horseName":"Urla Zamanı","raceId":8449,"kilo":57.0,"jokey":{"name":"ADEM ŞEN","raceNumber":280,"first":18,"second":25,"third":32,"fourth":32},"ekuriId":0},
{"horseId":51816,"horseName":"Wın Every Day","raceId":8449,"kilo":57.0,"jokey":{"name":"EMRE NALBANT","raceNumber":405,"first":19,"second":26,"third":36,"fourth":33},"ekuriId":0},
{"horseId":58650,"horseName":"Lıon Amed","raceId":8449,"kilo":52.0,"jokey":{"name":"CANER KARADEMİR","raceNumber":134,"first":7,"second":7,"third":8,"fourth":7},"ekuriId":0},
{"horseId":51239,"horseName":"Catch The Wınd","raceId":8449,"kilo":57.0,"jokey":{"name":"MÜSLÜM CANPOLAT","raceNumber":238,"first":5,"second":12,"third":12,"fourth":19},"ekuriId":0},
{"horseId":46263,"horseName":"Ian Tapp","raceId":8449,"kilo":58.0,"jokey":{"name":"ERDEM NUR TÜFEKÇİ","raceNumber":79,"first":3,"second":1,"third":4,"fourth":5},"ekuriId":0},
{"horseId":51647,"horseName":"Sılverado","raceId":8449,"kilo":57.0,"jokey":{"name":"ÜMİT DERYA ALTEKİN","raceNumber":1185,"first":48,"second":53,"third":64,"fourth":84},"ekuriId":0},
{"horseId":57231,"horseName":"Junıor Duru","raceId":8449,"kilo":58.0,"jokey":{"name":"BEDRİ TEPE","raceNumber":716,"first":45,"second":55,"third":50,"fourth":67},"ekuriId":0}
]};
It was basically an array but somebody on stackoverflow told the data inside ajax request should be an object so I added "horses:" to the front. The json is manually added inside the code.
This is http request:
$http({
url: 'http://localhost:8080/horseHistory',
method: 'POST',
contentType: "application/json",
data: list.horses,
headers: {
"Content-Type": "application/json"
}
}).success(function(data) {
console.log(data);
});
On the backend I just want to see a working http connection so it is mostly empty. This is spring-boot function:
#RequestMapping(value = "/horseHistory", method = RequestMethod.POST )
public ResponseEntity<Void> getHorseHistory(#RequestBody HorseRaceModel[] horseRaces) throws IOException {
System.out.println(horseRaces[0]);
return null;
}
HorseRaceModel:
package ganyan;
public class HorseRaceModel {
int horseId;
String horseName;
int raceId;
double kilo;
JokeyModel jokey;
int ekuriId;
public HorseRaceModel(int horseId, String horseName, int raceId, double kilo, JokeyModel jokey, int ekuriId) {
this.horseId = horseId;
this.horseName = horseName;
this.raceId = raceId;
this.kilo = kilo;
this.jokey = jokey;
this.ekuriId = ekuriId;
}
public int getHorseId() {
return horseId;
}
public void setHorseId(int horseId) {
this.horseId = horseId;
}
public void setHorseName(String horseName) {
this.horseName = horseName;
}
public String getHorseName() {
return horseName;
}
public int getRaceId() {
return raceId;
}
public void setRaceId(int raceId) {
this.raceId = raceId;
}
public double getKilo() {
return kilo;
}
public void setKilo(double kilo) {
this.kilo = kilo;
}
public JokeyModel getJokey() {
return jokey;
}
public void setJokey(JokeyModel jokey) {
this.jokey = jokey;
}
public int getEkuriId() {
return ekuriId;
}
public void setEkuriId(int ekuriId) {
this.ekuriId = ekuriId;
}
}
JokeyModel:
public class JokeyModel {
private String name;
private int raceNumber;
private int first;
private int second;
private int third;
private int fourth;
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRaceNumber() {
return raceNumber;
}
public void setRaceNumber(int raceNumber) {
this.raceNumber = raceNumber;
}
public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getThird() {
return third;
}
public void setThird(int third) {
this.third = third;
}
public int getFourth() {
return fourth;
}
public void setFourth(int fourth) {
this.fourth = fourth;
}
}
The error from Chrome console:
Failed to load resource: the server responded with a status of 400 (Bad Request) http://localhost:8080/horseHistory
The error from Java console:
nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.HashMap out of START_ARRAY token
I'm not familiar with Spring Boot and I don't know why you have been told to post a JSON object instead of a JSON array, but I see that you are not doing it coherently.
You wrapped your JSON array in a JSON object called list, but by specifying data: list.horses you are still only passing the embedded JSON array. Since you want to send the whole JSON object, you should specify data: list instead.
Furthermore, I think that you need to define the wrapper model on the server side, which may be some class like this:
public class ListModel {
private List<HorseRaceModel> horses;
public List<HorseRaceModel> getHorses() {
return horses;
}
public void setHorses(List<HorseRaceModel> horses) {
this.horses = horses;
}
}
Finally, the method consuming the post should be instructed to parse the request body into a ListModel. This means to modify the method to something like this:
#RequestMapping(value = "/horseHistory", method = RequestMethod.POST )
public ResponseEntity<Void> getHorseHistory(#RequestBody ListModel horseRaces) throws IOException {
System.out.println(horseRaces.getHorses().get(0).getName());
return null;
}
Side note: I also modified the code to print the name of the first horse instead of the object pointer that would be printed by System.out.println(horseRaces.getHorses().get(0));. You may want to print something else instead. You may also want to use better names for the wrapper object and model (instead of list and ListModel)
Note from comment: Your HorseRaceModel class does not have an empty constructor, you need to provide one for deserialization to work

JQuery request not working in Chrome and Firefox. Works in IE

I have a WCF service being hosted locally and a website also being hosted locally. I make a GET ajax request for JSON data which I handle on success. I have a problem where in Chrome and Firefox it goes into the error block of the Ajax request.
<!--jQuery dependencies-->
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/themes/base/jquery-ui.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.1/jquery-ui.min.js"></script>
<script type="text/javascript" src="../../Library/JS/pqgrid.min.js"></script>
<script type="text/javascript">
var jqNew = $.noConflict(true);
</script>
Because of the complexity of the website, I am using two different versions of JQuery. The newer version has the alias of jqNew.
jqNew(document).ready(function () {
$($.ajax({
url: "http://wks52025:82/WcfDataService.svc/GetNotesFromView()?$format=json",
type: "GET",
datatype: "json",
async: false,
success: function (data, textStatus) {
alert(textStatus);
$.each(data.d, function (i, item) {
alert(i);
DataArray[i] = [];
DataArray[i][0] = item.NotesID;
DataArray[i][1] = item.NotesTitle;
DataArray[i][2] = item.NotesText;
DataArray[i][3] = item.ProfileName;
DataArray[i][4] = item.IsShared;
DataArray[i][5] = item.NameOfUser;
});
},
error: function (data, textStatus) {
alert(textStatus);
}
})).then(buildGrid(DataArray));
This is my request. It is synchronous because I want the data before I build my grid. It is a GET request because all I want is to retrieve data. I am not doing a cross-domain request because everything is happening locally, at least I think it's local because the website and service is localhost.
//------------------------------------------------------------------------------
// <copyright file="WebDataService.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Data.Services;
using System.Data.Services.Common;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
using System.Data.Services.Parsing;
using WCFNotes;
[JSONPSupportBehavior]
public class WcfDataService : DataService< GenesisOnlineEntities >
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
// TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
// Examples:
config.UseVerboseErrors = true;
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
config.SetServiceOperationAccessRule("GetNotes", ServiceOperationRights.AllRead);
config.SetServiceOperationAccessRule("GetNotesFromView", ServiceOperationRights.AllRead);
config.SetServiceOperationAccessRule("AddNewNote", ServiceOperationRights.All);
config.SetServiceOperationAccessRule("UpdateNote", ServiceOperationRights.All);
config.SetServiceOperationAccessRule("DeleteNote", ServiceOperationRights.All);
}
protected override void OnStartProcessingRequest(ProcessRequestArgs args)
{
base.OnStartProcessingRequest(args);
//Cache for a minute based on querystring
//HttpContext context = HttpContext.Current;
HttpCachePolicy c = HttpContext.Current.Response.Cache;
c.SetCacheability(HttpCacheability.NoCache);
//c.SetExpires(HttpContext.Current.Timestamp.AddSeconds(60));
c.VaryByHeaders["Accept"] = true;
c.VaryByHeaders["Accept-Charset"] = true;
c.VaryByHeaders["Accept-Encoding"] = true;
c.VaryByParams["*"] = true;
}
[WebGet]
public IQueryable<tblNote> GetNotes()
{
IQueryable<tblNote> biglist = (from c in this.CurrentDataSource.tblNotes select c);
return biglist;
}
[WebGet]
public IQueryable<vw_Note> GetNoteByID(Guid NoteID)
{
IQueryable<vw_Note> biglist = (from c in this.CurrentDataSource.vw_Notes where c.NotesID.Equals(NoteID) select c);
return biglist;
}
[WebGet]
public IQueryable<vw_Note> GetNotesFromView()
{
Guid UserID = new Guid("8b0e303a-68aa-49a5-af95-d994e2bdd5ac");
IQueryable<vw_Note> biglist = (from c in this.CurrentDataSource.vw_Notes select c);
return biglist;
}
//[WebGet]
//public void AddNewNote(string ParamNoteTitle, string ParamNoteText)
//{
// //My hardcoded values for now...
// int ParentID = 8879;
// int JobID = 1000088150;
// int ContactID = 309;
// Guid UserID = Guid.NewGuid();
// string RelatedType = "Advertiser Contact";
// bool IsShared = true;
// tblNote N = new tblNote
// {
// NotesTitle = ParamNoteTitle,
// NotesText = ParamNoteText,
// ParentID = ParentID,
// ContactID = ContactID,
// JobID = JobID,
// UserID = UserID,
// GroupID = null,
// RelatedType = RelatedType,
// IsShared = IsShared
// };
// try
// {
// this.CurrentDataSource.tblNotes.Add(N);
// this.CurrentDataSource.SaveChanges();
// }
// catch (Exception ex)
// {
// }
//}
[WebGet]
public IQueryable<vw_Note> AddNewNote(string ParamNoteTitle, string ParamNoteText)
{
//My hardcoded values for now...
int ParentID = 8879;
int JobID = 1000088150;
int ContactID = 309;
Guid UserID = new Guid("8b0e303a-68aa-49a5-af95-d994e2bdd5ac");
Guid NoteID = Guid.NewGuid();
string RelatedType = "Advertiser Contact";
bool IsShared = true;
tblNote N = new tblNote
{
NotesID = NoteID,
NotesTitle = ParamNoteTitle,
NotesText = ParamNoteText,
ParentID = ParentID,
ContactID = ContactID,
JobID = JobID,
UserID = UserID,
GroupID = null,
RelatedType = RelatedType,
IsShared = IsShared
};
try
{
this.CurrentDataSource.tblNotes.Add(N);
this.CurrentDataSource.SaveChanges();
return GetNoteByID(NoteID);
}
catch (Exception ex)
{
return GetNoteByID(NoteID);
}
}
[WebGet]
public IQueryable<vw_Note> UpdateNote(string NoteID, string ParamNoteTitle, string ParamNoteText)
{
//My hardcoded values for now...
Guid GNoteID = Guid.Parse(NoteID);
try
{
tblNote n = CurrentDataSource.tblNotes.First(i => i.NotesID == GNoteID);
n.NotesTitle = ParamNoteTitle;
n.NotesText = ParamNoteText;
this.CurrentDataSource.SaveChanges();
return GetNoteByID(GNoteID);
}
catch (Exception ex)
{
return GetNoteByID(GNoteID);
}
}
[WebGet]
public IQueryable<vw_Note> DeleteNote(string NoteID)
{
Guid GNoteID = Guid.Parse(NoteID);
tblNote N = new tblNote
{
NotesID = GNoteID,
};
try
{
this.CurrentDataSource.tblNotes.Attach(N);
this.CurrentDataSource.tblNotes.Remove(N);
this.CurrentDataSource.SaveChanges();
// IF doesn't return value, delete was successful
return GetNoteByID(GNoteID);
}
catch (Exception ex)
{
return GetNoteByID(GNoteID);
}
}
}
This is my WCF service. Configuration is at the top of the code block.
Anyone know why this doesn't work in firefox and chrome?

GWT Native Method Warning

I'm doing a project in GWT to deploy in AppEngine and I'm getting a warning in Eclipse saying:
JavaScript parsing: Expected an identifier in JSNI
reference
Any ideas on what's causing this?
public void callFacebookAPI(String url) {
JsonpRequestBuilder requestBuilder = new JsonpRequestBuilder();
requestBuilder.requestObject(url, new AsyncCallback<FbUser>() {
public void onFailure(Throwable caught) {
System.out.println("FAIL" );
}
#Override
public void onSuccess(FbUser result) {
facebookUser = result;
System.out.println("Facebook name:" + facebookUser.getName());
}
});
}
private final native void doFbLoginFunction() /*-{
FB.login(function(response) {
if (response.authResponse) {
// connected
//return response.session;
var accessToken = response.accessToken;
var url = "http://graph.facebook.com/me?access_token=";
var facebookUrl = url + accessToken;
#com.google.gwt.smartpark.client.map.SmartPark::callFacebookAPI(Ljava/lang/String;Ljava/lang/
String;)(facebookUrl);
} else {
// cancelled
}
});
callFacebookAPI is not static so there must be something before the # in the reference in JSNI, e.g.
var that = this;
$wnd.FB.login($entry(function(response) {
// ...
that.#com.google.gwt.smartpark.client.map.SmartPack::callFacebookAPI(Ljava/lang/String;)(facebookUrl);
// ...
}));
Also, your callFacebookAPI takes a single argument, so the JSNI signature should have a single Ljava/lang/String;.

Categories

Resources