JSON data not being saved in WebAPI - javascript

I'm following a Pluralsight course on AngularJS and WebAPI together. I'm trying to save data being sent from the client to the server using PUT, but the data is not saving and I'm not getting any errors. Also, It doesn't event hit the correct server side code because the breakpoints are not being caught. I've tried to change the type of HTTP method, but I need this one. The only thing being sent back is a "204: No Content" code from the server.
This is how the PUT and POST methods look like. Breakpoints in any of these methods will not be captured.
// POST: api/Products
public void Post([FromBody]Product product) // Creating a product
{
var productRepository = new ProductRepository();
var newProduct = productRepository.Save(product);
}
// PUT: api/Products/5
public void Put(int id, [FromBody]Product product) // Updating a product
{
var productRepository = new ProductRepository();
var updatedProduct = productRepository.Save(id, product);
}
ProductRepository looks like this:
internal Product Save(Product product)
{
// Read in the existing products
var products = this.Retrieve();
// Assign a new Id
var maxId = products.Max(p => p.ProductID);
product.ProductID = maxId + 1;
products.Add(product);
WriteData(products);
return product;
}
internal Product Save(int id, Product product)
{
// Read in the existing products
var products = this.Retrieve();
// Locate and replace the item
var itemIndex = products.FindIndex(p => p.ProductID == product.ProductID);
if (itemIndex > 0)
{
products[itemIndex] = product;
}
else
{
return null;
}
WriteData(products);
return product;
}
This is the main part of the controller that is being used (using Controller-As syntax:
var vm = this;
vm.submit = function () {
vm.message = "";
if (vm.product.productID) {
vm.product.$update({ id: vm.product.productID }, function (data {
console.log(data);
vm.message = "Save Complete";
});
} else {
vm.product.$save(function (data) {
vm.originalProduct = angular.copy(data);
vm.message = "Save Complete";
});
}
};
Finally, productResource is a custom service that looks like this:
var productResource = function($resource, appSettings) {
return $resource(appSettings.serverPath + "/api/Products/:id", null, {
'update': { method: 'PUT' }
});
}
I've tried to look to see if it's a CORS problem, but it's not since I have it enabled at the class level.

Please check your API if it implements CORS(Cross Origin Resource Sharing)

Shouldn't
var itemIndex = products.FindIndex(p => p.ProductID == product.ProductID);
be
var itemIndex = products.FindIndex(p => p.ProductID == id);

Related

.Net 6 - Different session for each browser tab – diff images in each

I been having some major issues with this, I feel like this shouldn’t be so hard but..
I am trying to be able to open a link which brings pictures to the browser to display them. I have this working.
What I am trying to do is when someone opens another link itll open a new tab and they will have those new pictures in that tab and the previous pictures in the other tab. I tried to do this with Sessions but it overwrites the session, and both tabs show the same pics. I now coded it up so I have a different session guid for each tab and I go to try to view the pics but the same thing happens. The tab is over written.
My new idea is to save this huge text file in a hidden variable on the page and read from that. But when I do this my tempdata var says the page cannot be found but if I remove the tempdata var the page works…
I rewrote a bunch of methods some multiple times.
Any ways to make this work would be greatly appreciated
public async Task<ActionResult> PopulateFileCache(string folderPath)
{
if (!string.IsNullOrEmpty(folderPath))
{
using var client = _httpClient.CreateClient("MesserAPI");
try
{
using var response = await client.GetAsync($"/api/File/GetFolderFiles?folderPath={folderPath}");
if (response.IsSuccessStatusCode)
{
var lstFiles = await response.Content.ReadAsStringAsync();
ViewData["lstParts"] = lstFiles;
TempData["SlideTotal"] = 0;
if (_contextAccessor.HttpContext.Session.IsAvailable)
{
SaveToSession(lstFiles);
}
TempData["guid"] = _contextAccessor.HttpContext.Session.GetString("sGUID") ?? string.Empty;
}
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
}
return RedirectToAction("FileViewer");
}
public IActionResult ReturnData(string sessionID)
{
//if (objFiles != null)
//{
if (TempData != null)
{
TempData.Keep();
}
List<LNPartVM> lNParts = null;
try
{
//var jsonResponse = objFiles;
//var jsonResponse = GetFromSession();
var jsonResponse = GetFromSession(sessionID);
if (!string.IsNullOrWhiteSpace(jsonResponse))
{
lNParts = JsonSerializer.Deserialize<List<LNPartVM>>(jsonResponse);
}
if (lNParts?.Count > 0)
{
TempData["SlideTotal"] = lNParts.Count;
_contextAccessor.HttpContext.Session.SetInt32("SlideTotal", lNParts.Count);
int partIndex = 0;
try
{
partIndex = (int)(_contextAccessor.HttpContext.Session.GetInt32("PartIndex") == null ? 0 : _contextAccessor.HttpContext.Session.GetInt32("PartIndex"));
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
LNPartVM partVM = lNParts[partIndex];
}
catch (Exception ex)
{
_logger.LogError(ex.Message);
}
//}
return ViewComponent("DataPage");
}
public string GetSessionID()
{
return _contextAccessor.HttpContext.Session.Id;
}
public string GetSessionGUID()
{
return Guid.NewGuid().ToString();
}
//string sessionName,
public IActionResult SaveToSession(string obj)
{
bool status = false;
// Same Session across browsers
//string sessionID = GetSessionID();
string sessionID = GetSessionGUID();
if (!string.IsNullOrWhiteSpace(sessionID))
{
_contextAccessor.HttpContext.Session.SetString(sessionID, obj);
_contextAccessor.HttpContext.Session.SetString("sGUID", sessionID);
status = true;
}
else
{
_contextAccessor.HttpContext.Session.SetString("SessionPN", obj);
status |= true;
}
if (status)
{
return Content("Session Saved");
}
return Content("Session Error");
}
public async Task<IActionResult> FileViewer()
{
return View();
}
This is on the HTML page
$('#btnNext').click(function (e) {
e.preventDefault();
console.log(iSlideCount);
if (iSlideCount > 0) {
$.ajax({
type: 'GET',
url: '#Url.Action("NextPart", "File")',
contentType: 'Json'
})
.done(function(e) {
var sguid = $("#txthguid").val();
var route = '#Url.Action("ReturnData","File", new { sessionID="-1" })';
route = route.replace("-1", sguid);
$('#contentData').load(route);
//$('#contentData').load('#Url.Action("ReturnData","File")');
//$('#part').load('#Url.Action("ReturnData","File")');

.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="

Send single item of list from view to controller via AJAX

I have a view composed of a list of users:
#model List<LabelPrinting.Models.UserModel>
and I put these into a JavaScript object:
users = function () { return #Html.Raw(Json.Encode(Model)) }();
I then load a jQuery accordion with the values for each. I then choose to print avery labels for a particular user in the list and set a value. I'm trying to send only that particular user to the controller and am getting a null values for of the user properties:
function PrintAveryLabel(but) {
var id = but.id.substring(9);
var $rad = $(but).closest('tr').siblings().find('.radLabelOther');
if (($rad).is(':checked')) {
var $txtr = $rad.closest('tr').siblings().find('.classRows');
var $txtc = $rad.closest('tr').siblings().find('.classCols');
if ($txtr.val() === "0" || $txtc.val() === "0") {
$("#lblError").text("You have have not selected the rows and columns for the labels.");
$("#MessageDialog").dialog({ title: "Select Rows/Columns" });
$("#MessageDialog").dialog("open");
return false;
}
}
var data = findUser(id);
$.ajax({
type: 'POST',
data: { pat: data },
url: '#Url.Action("PrintUserLabels")'
});
}
The findUser function simply picks the entry in the list that matches the ID.
function findUser(id) {
var data;
for (i = 0; i < cnt; i++) {
if (users[i].UserId === parseInt(id)) {
data = users[i];
break;
}
}
return data;
}
My controller action:
[HttpPost]
public ActionResult PrintUserLabels(UserModel pat)
{
string retval = "";
if (pat.PrintLabel)
{
return RedirectToAction("Label", new { user = pat });
}
else
{
retval = "ERROR - you must make a selection";
Exception e = new Exception(retval);
HandleErrorInfo info = new HandleErrorInfo(e, "DYMO", "PrintPatientLabels");
return RedirectToAction("Error", info);
}
}
The label action is tried and true but I get a null user model. What am I doing wrong?

breeze doesn't recognize the modified entity

I have a breeze implementation where it takes a location object and displays the properties on the UI. I do a change to a few properties and try to save the changes, but breeze doesn't recognized the entity as changed. Following is my code:
[HttpGet]
[CustomAuthorize(Claims = "permission:CanViewLocationAttributes")]
public Location GetLocationById(int clientId, int locationId)
{
//returns a single Location object
}
Following is my client-side functionality to retrieve the entity and save the entity:
function getLocationById(clientId, locationId) {
var self = this;
return EntityQuery.from('GetLocationById')
.withParameters({ clientId: clientId, locationId : locationId })
.using(self.manager)
.execute()
.then(querySucceeded, this._queryFailed);
function querySucceeded(data) {
if (data.results.length > 0) {
return data.results[0];
}
logSuccess(localize.getLocalizedString('_RetrievedLocations_'), locations, true);
}
}
function saveLocationSettings(clientId) {
var self = this;
var saveOptions = this.manager.saveOptions.using({ resourceName: "SaveLocationSettings", allowConcurrentSaves: true });
var entitiesToSave = self.manager.getChanges();
return self.manager.saveChanges(entitiesToSave, saveOptions).then(saveSucceeded, saveFailed);
}
my problem is that here the value of entitiesToSave is 0, even after I make changes to the fields in UI and save them.
Following is how I bind the entity to my angular model:
function getLocationDetails() {
clientcontext.location.getLocationById($route.current.params.clientId, $route.current.params.id)
.then(function (data) {
basicLocationSettings.id = data.locationId;
basicLocationSettings.parent = data.fkParentLocationId;
basicLocationSettings.locationType = data.locationType;
basicLocationSettings.locationName = data.locationName;
basicLocationSettings.locationDisplayName = data.locationDisplayName;
basicLocationSettings.locationCode = data.locationCode;
basicLocationSettings.isActive = data.activeStatus;
basicLocationSettings.timeZone = data.fkTimeZoneId;
basicLocationSettings.usesAppointments = data.usesAppointments;
basicLocationSettings.availabilityWindowDays = data.availabilityWindowDays;
basicLocationSettings.appointmentCutOffDays = data.appointmentCutOffDays;
basicLocationSettings.dailySummaryEmailTime = data.dailySummaryEmailTime;
basicLocationSettings.reminderBeforeApptEmailTime = data.reminderBeforeApptEmailTime;
basicLocationSettings.saveLocationSettings = function () {
clientcontext.location.saveLocationSettings($route.current.params.clientId);
}
});
}
Can anyone explain what I'm doing wrong? This is my first attempt on breeze and I'm kind of stuck here.
It looks like you are copying the breeze location entity's property values into an pojo object variable named "basicLocationSettings". Any changes to basicLocationSettings will not be tracked by the breeze entity manager or reflected in the source breeze entity. You'll need to bind the actual breeze entity to your UI so that user data entry modifies the entity property values directly.
I modified my code as follows and now the save is working:
function getLocationById(clientId, locationId) {
var self = this;
var location = null;
return EntityQuery.from('GetLocationById')
.withParameters({ clientId: clientId, locationId : locationId })
.using(self.manager)
.execute()
.then(querySucceeded, this._queryFailed);
function querySucceeded(data) {
if (data.results.length > 0) {
location = data.results[0];
}
logSuccess(localize.getLocalizedString('_RetrievedLocations_'), locations, true);
return location;
}
}
Note that I'm returning a location object, and in my controller, I bind the location object to my POJO.
function getLocationDetails() {
clientcontext.location.getLocationById($route.current.params.clientId, $route.current.params.id)
.then(function (data) {
basicLocationSettings.location = data;
basicLocationSettings.saveLocationSettings = saveLocationSettings;
});
}
Now when I call saveChanges(), I pass the location object to the repository:
function saveLocationSettings() {
clientcontext.location.saveLocationSettings(basicLocationSettings.location);
}

Ajax call to ASP.NET MVC Controller Returns 404 when Json Length is too Long

I have a simple ajax call which is passing a json string to a controller action and if the content portion of the json is too long, or the json string in general, the server returns a 404, if I shorten the content, it the request resolves and completes correctly.
I thought it was do to the 8k limit of Microsoft's JavaScriptSeralizer, but I have updated the MaxJsonLength, with no luck. Can somebody please tell me what's going on here?
Here is my ajax request (Note: This is using Knockout.js)
self.updatePost = function () {
var postToUpdate = ko.toJS(self.selectedPost);
postToUpdate.Content = $("#wmd-input").val();
console.log(postToUpdate);
$.getJSON('/blogs/posts/update', {post: ko.toJSON(postToUpdate)}, function(post) {
if (post) {
// remove the selected post and add the updated post
self.posts.remove(self.selectedPost());
var updatedPost = new Post(post);
self.posts.unshift(updatedPost);
self.selectedPost(updatedPost);
$("#ghost-list li:first").trigger('click');
// show alert
}
});
};
The C# Controller Action
public JsonResult Update(string post)
{
var seralizer = new JavaScriptSerializer();
seralizer.MaxJsonLength = int.MaxValue;
seralizer.RecursionLimit = 100;
var selectedPost = seralizer.Deserialize<Post>(post);
var student = students.GetStudentByEmail(User.Identity.Name);
var blog = db.Blogs.SingleOrDefault(b => b.StudentID == student.StudentID);
var postToUpdate = blog.BlogPosts.SingleOrDefault(p => p.ID == selectedPost.ID);
if (postToUpdate != null)
{
// update the post fields
postToUpdate.Title = selectedPost.Title;
postToUpdate.Slug = BlogHelper.Slugify(selectedPost.Title);
postToUpdate.Content = selectedPost.Content;
postToUpdate.Category = selectedPost.Category;
postToUpdate.Tags = selectedPost.Tags;
postToUpdate.LastUpdated = DateTime.Now;
if (selectedPost.Published)
{
postToUpdate.DatePublished = DateTime.Now;
}
// save changes
db.SaveChanges();
var jsonResult = Json(seralizer.Serialize(selectedPost), JsonRequestBehavior.AllowGet);
jsonResult.MaxJsonLength = int.MaxValue;
return jsonResult;
}
return Json(false, JsonRequestBehavior.AllowGet);
}
Have you tried using the post method:
$.post('/blogs/posts/update', {post: ko.toJSON(postToUpdate)}, function(post) {
if (post) {
// remove the selected post and add the updated post
self.posts.remove(self.selectedPost());
var updatedPost = new Post(post);
self.posts.unshift(updatedPost);
self.selectedPost(updatedPost);
$("#ghost-list li:first").trigger('click');
// show alert
}
}, 'json');
Try this at web config
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="500000000"/>
</webServices>
</scripting></system.web.extensions>

Categories

Resources