I’ve been battling this problem now for a few hours, and have tried several solutions (including using dataset, datareader to access the data, converting the datareader/dataset into a list of objects and then sending the result as a Json. I’ve also tried using Json.Net and a replacing the $http with an AJAX call, all to no avail.
In an MVC4 project, I’ve detailed an angular controller to retrieve data from our ACCESS database. An $http request is sent to the (local)server, received, and executed. The results generated, however, are not received back by the angular controller.
Any and all help will be greatly appreciated
This is the method:
[HttpPost]
public JsonResult GetCatalogueItems(string get)
{
JsonResult toReturn = null;
string cs = ConfigurationManager.ConnectionStrings["connStringPT"].ConnectionString;
OleDbConnection cn = new OleDbConnection(cs);
string queryStart = " SELECT catNum, testName, price, comments FROM table_catalog WHERE ";
DataSet ds = new DataSet();
try
{
List<ptProductModel> listToReturn = new List<ptProductModel>();
string query = queryStart + get + "=true;";
cn.Open();
OleDbCommand cmd = new OleDbCommand(query, cn);
OleDbDataReader reader = cmd.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
ptProductModel item = new ptProductModel
{
Number = reader[0].ToString(),
Name = reader[1].ToString(),
//comment = reader.GetString(reader.GetOrdinal("comments")) !=null ? reader.GetString(reader.GetOrdinal("comments")) : null,
price = reader[2].ToString()
};
listToReturn.Add(item);
}
reader.Close();
if (cn.State == ConnectionState.Open)
{
cn.Close();
}
toReturn = Json(listToReturn.Select(s => new { Name = s.Name, price = s.price, Number = s.Number }), JsonRequestBehavior.AllowGet);
}
}
catch (OleDbException ex)
{
toReturn = Json("Error", JsonRequestBehavior.AllowGet);
}
return toReturn;
}
}
And this is the angular controller:
myApp.controller('ptCatalogueController', ['$scope', '$http', function ($scope, $http) {
$scope.catalogueItems = [];
$scope.Product = "";
$scope.Init = function () { }
$scope.GetProducts = function (productSet) {
console.error(productSet, 'blabla');
$http.post({
url: '/Catalogue/GetCatalogueItems', data: { get: productSet }
}).then(
// success callback
function (data) {
$scope.catalogueItems = data;
console.log($scope.catalogueItems);
console.debug("success");
}
,
//error callback
function (response) {
console.log(response);
console.debug("error");
}
)}
}]);
and the header:
POST /Catalogue/[object%20Object] HTTP/1.1
Host: localhost:49078
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,he;q=0.6
Cookie: ASP.NET_SessionId=fvfswezab5g1ekyiuotmpw3m
Origin: http://localhost:49078
Referer: http://localhost:49078/Catalogue/Index
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
X-DevTools-Emulate-Network-Conditions-Client-Id: 0689EBCB-E24D-48E3-ACF9-0D94BB0B6F16
HTTP/1.1 404 Not Found
Cache-Control: private
Content-Length: 3732
Content-Type: text/html; charset=utf-8
Date: Sun, 22 Nov 2015 07:59:03 GMT
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-SourceFiles: =?UTF-8?B? RTpcR2VuZXJhbCBGb2xkZXJcRGV2ZWxvcG1lbnRcV2ViLVBzeWNoVGVjaC1OZXdTaXRlXFdlYi1Qc3ljaFRlY2gtTmV3U2l0ZVxDYXRhbG9ndWVcW29iamVjdCBPYmplY3Rd?=
Related
I have a netcoreapp2.1 webapp which is presenting an issue in Google Chrome, but not Edge or IE, during the OIDC flow redirect. It simply stops at http://localhost:5000/signin-oidc with this response received:
General:
Request URL: http://localhost:5000/signin-oidc
Request Method: POST
Status Code: 500 Internal Server Error
Remote Address: [::1]:5000
Referrer Policy: no-referrer-when-downgrade
Response Headers:
Content-Length: 0
Date: Tue, 04 Aug 2020 09:49:32 GMT
Server: Kestrel
Request Headers:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
Content-Length: 2148
Content-Type: application/x-www-form-urlencoded
Host: localhost:5000
Origin: null
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36
Form Data:
code: Ry9Pec...rdG1U0SB
scopes: resource.WRITE+openid+resource.READ
state: CfDJ8JZ...oESbUvQ
id_token: eyJhbG...9sXMEhs
When I visit localhost:5000 in chrome (incognito or not) the code never reaches the OnTicketReceived event, whereas when fired from IE, Edge etc it does, and proceeds just fine.
This is the startup class:
public class Startup
{
private AppSettings _appSettings;
private IConfiguration _config;
public Startup(IConfiguration configuration)
{
_config = configuration;
_appSettings = _config.Get<AppSettings>();
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.Configure<AppSettings>(_config);
services.AddSingleton<IAPIRepository, APIRepository>();
services.AddSingleton<IUserRepository, UserRepository>();
services.AddSingleton<INavigationRepository, NavigationRepository>();
services.UseOpenIDConnectMiddleware(new OpenIDConnectMiddlewareOptions
{
BaseUrl = _appSettings.API.BaseUrl,
AppName = _appSettings.AppName,
ClientId = _appSettings.API.ClientId,
ClientSecret = _appSettings.API.ClientSecret,
Secure = !_appSettings.Local
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
if (!_appSettings.Local)
{
app.UseGlobalLoginMiddleware();
}
if (_appSettings.FeatureFlags["ProcessRedirectionRules"])
{
app.UseRedirectUserMiddleware(_appSettings.RedirectionRules);
}
app.UseMvc();
app.UseProtectHTMLRouteMiddleware();
if (_appSettings.Local)
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
ProjectPath = Path.Join(Directory.GetCurrentDirectory(), "../UI"),
ConfigFile = "node_modules/#vue/cli-service/webpack.config.js",
HotModuleReplacement = true
});
}
else
{
app.UseDefaultFiles();
app.UseStaticFiles();
}
app.UseJavascriptVarMiddleware(new JavascriptSettingsMiddlewareOptions
{
FileName = "env.js",
ObjectName = "__env",
Settings = new Dictionary<string, string>
{
{ "insightsKey", _appSettings.ApplicationInsights.InstrumentationKey },
{ "environment", _appSettings.Environment },
{ "gatekeeperBaseUrl", _appSettings.Gatekeeper.BaseUrl }
}
});
app.UseGlobalSignoutMiddleware(new GlobalSignoutMiddlewareOptions
{
GatekeeperLogoutUrl = _appSettings.API.LogoutUrl
});
app.UseHTMLRouteFallback(new HTMLRouteFallbackMiddlewareOptions
{
Local = _appSettings.Local,
Path = Path.Join(Directory.GetCurrentDirectory(), "../UI/dist")
});
}
}
I have cleaned the localhost and localhost:5000 cookies from the browser.
A quick guess would be that it is a SameSite cookie issue that different browsers handle differently due to various bugs.
This article might give you a starting point:
How To Prepare Your IdentityServer For Chrome's SameSite Cookie Changes - And How To Deal With Safari, Nevertheless
Also, your Configure method looks very odd. Because the ordering of the App.Use statements matter and usually you would put the app.UseMvc(); last in that method. Each incoming request will pass through those middlewares that the App.UseXXX adds and if the ordering is not correct then you will have issues.
I am using an MVC relay controller to call a Web Api controller to get around the PUT limitation in forms/browsers. The relay works fine. The problem is that the response when displayed just shows the response code and headers and not the JSON content that is also returned.
Here is the code that does the relay:
[HttpPost]
public async Task<HttpResponseMessage> UpdateTicket(int reference, TicketUpdateDTO ticket)
{
HttpClient client = new HttpClient();
var baseUri = string.Format("{0}://{1}{2}", Request.Url.Scheme,
Request.Url.Host, Request.Url.Port == 80 ? string.Empty : ":" + Request.Url.Port);
client.BaseAddress = new Uri(baseUri);
HttpResponseMessage responseMessage = await client.PutAsJsonAsync("api/Tickets/" + reference, ticket);
var content = await responseMessage.Content.ReadAsStringAsync();
return responseMessage;
}
And here is what is actually returned and displayed in a browser:
StatusCode: 201, ReasonPhrase: 'Created', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: { Pragma: no-cache X-SourceFiles: =?UTF-8?B?QzpcRGV2ZWxvcFxFeHRyZW1lSVRTXEV4dHJlbWVJVFNcYXBpXFRpY2tldHNcMTAwMDAwMg==?= Cache-Control: no-cache Date: Fri, 26 Feb 2016 16:32:57 GMT Location: http://localhost:59413/api/tickets/1000002 Server: Microsoft-IIS/10.0 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Content-Length: 419 Content-Type: application/json; charset=utf-8 Expires: -1 }
When I check the content, it is returning the object correctly in JSON format, but I am not sure why it isn't showing up in the browser with all the other parts of the HTTP response not shown.
I have an Web Api controller for access data from server:
public class ServicesController : ApiController
{
[AcceptVerbs("POST")]
public IList<TreeMenuItem> LoadMetadata()
{
List<TreeMenuItem> itemsMenu = new List<TreeMenuItem>();
TreeMenuItem dataSource = new TreeMenuItem("1", "DataSources", null);
itemsMenu.Add(dataSource);
return itemsMenu;
}
}
which is call by an angularJS controler:
angular.module('App').
controller('TreeMenuController', ["$scope", "$http", treeMenuController]);
function treeMenuController($scope, $http) {
var baseUrl = "api/Services/LoadMetadata";
$http.post(baseUrl)
.then(function (result) {
$scope.roleList = result.data;
});
};
In browser network I have:
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip,deflate
Content-Length:2
Content-Type:application/json;charset=UTF-8
Request Payload
{}
Response Headers:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 4
in Response tab: [{}].
What is wrong?
I make it work:
The big help was the response message when I put in browser the address for accessing api services (api/Services/LoadMetadata):
The error answer was in an xml file where I found that was problem with serialization of the object TreeMenuItem. The advice was to decorate with DataContract the class and DataMember the class properties - like in WCF. After I did that (was need to add reference in project to System.Runtime.Serialization), everything was perfect.
It takes nearly 50 seconds to load a big chunk of 35 MB Json when accessing the Api. So to improve performance I added the WebApiContrib.Formatting.ProtoBuf to my project. The data is displayed in a Kendo UI Grid.
What am I missing here? A dataType or type in the View, or anything like that? And are there other or better ways to improve the performance?
Here some snippets->
POCO-Class:
[ProtoContract]
public partial class KDAuftraege
{
[ProtoMember(1)]
public int AngebotsNummer { get; set; }
[ProtoMember(2)]
public Nullable<int> BesuchsNummer { get; set; }
[ProtoMember(3)]
public Nullable<int> Kennummer { get; set; }
[ProtoMember(4)]
View:
var remoteDataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/api/WebApiAuftraege'
},
},
Controller:
public IQueryable<KDAuftraege> GetKDAuftraeges()
{
//return db.KDAuftraeges.Take(500);
return db.KDAuftraeges;
}
WebApi:
config.Formatters.Add(new ProtoBufFormatter());
Headers:
Cache-Control no-cache
Content-Length 36227588
Content-Type application/json; charset=utf-8
Date Sat, 07 Jun 2014 09:23:54 GMT
Expires -1
Pragma no-cache
Server Microsoft-IIS/8.0
X-AspNet-Version 4.0.30319
X-Powered-By ASP.NET
X-SourceFiles =?UTF-8?B?YzpcdXNlcnNcb2xkc3BvcnRcZG9jdW1lbnRzXHZpc3VhbCBzdHVkaW8gMjAxM1xQcm9qZWN0c1xWaXM0XFZpczRcYXBpXFdlYkFwaUF1ZnRyYWVnZQ==?=
Anfrage-HeaderQuelltext anzeigen
Accept */*
Accept-Encoding gzip, deflate
Accept-Language de,en-US;q=0.7,en;q=0.3
Connection keep-alive
Cookie __RequestVerificationToken=wMVQWPOkXsB2XDIFN_07RJDtKqN_90dLRYaBYJGsFSGEHTcQ1S6e15mPiWrvkMHS8HrAlHYAI0OVSkqtPQHFVMP5DxoyccijSktL_KsoEFU1; .AspNet.ApplicationCookie=RTQ61CfArDWHlWN06eOpZiZY6NmFGp0SwCCuR8bQCtnItSz6S8YTasQu4-uoRQCc-XqWDCZmtOpEb-b0SyIioQPomkm1BrKywMcVwt3bF_JBxORKGg-UNSHyPvFyBohiS1sJ354LpRHIjrPIA8rUexvZih4VrK9lvHu_sm21ncNXXV7jATKAjTdX7J3XvfxRsF11fhgDNtpXPEWxQPjD7Rkj5yvdqI-vbfr9tfQbszUR1O3oOjYcRxUvvVrJ7xnt-caxt-o_Kut1dixLEA241pMGPCHfetWK73Yp148K3X9By6ylHFOTEjjDwHZyHLIrBwwOZ-ujnaOf20jQzeZXaF16bHxeadLYuKK-Z2DpdzaJXPzZd2pBbzHJMFX7USfZmp7OZzLpOitLCMovGHwdRiLD0F2NR1a0iTHCgiZLvA8
Host localhost:19275
Referer http://localhost:19275/MvcAuftraege
User-Agent Mozilla/5.0 (Windows NT 6.3; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0
X-Requested-With XMLHttpRequest
Options 1: Change your view DataSource code (I think this is right)
var remoteDataSource = new kendo.data.DataSource({
transport: {
read: {
type: 'GET',
headers: { Accept: 'application/x-protobuf' },
url: '/api/WebApiAuftraege'
},
},
Option 2: Change your Web API Formatters so that ProtoBuf is the default:
config.Formatters.Insert(0, new ProtoBufFormatter());
I use the following JavaScript/jQuery function to make a remote procedure call through JSON.
<s:url var="testJsonUrl" action="testJsonAction"/>
<script src="../js/jquery-1.8.0.min.js" type="text/javascript"></script>
var timeout;
var request;
$(document).ready(function(){
$("#countryComboBox").change(function(){
if(!request)
{
request = $.ajax({
datatype:"json",
type: "POST",
data: JSON.stringify({jsonrpc:'2.0', method:'getStateTables', id:'jsonrpc', params:[$("#countryComboBox").val()]}),
contentType: "application/json-rpc; charset=utf-8",
url: "<s:property value='#testJsonUrl'/>",
success: function(response)
{
alert(JSON.stringify(response.result));
},
complete: function()
{
timeout = request = null;
},
error: function(request, status, error)
{
if(status!=="timeout"&&status!=="abort")
{
alert(status+" : "+error);
}
}
});
timeout = setTimeout(function() {
if(request)
{
request.abort();
alert("The request has been timed out.");
}
}, 30000);
}
});
});
This function invokes the method getStateTables() in an action class which is as follows.
#Namespace("/admin_side")
#ResultPath("/WEB-INF/content")
#ParentPackage(value = "json-default")
public final class TestAction extends ActionSupport
{
#Autowired
private final transient SharableService sharableService = null;
private static final long serialVersionUID = 1L;
List<StateTable> stateTables;
public TestAction() {}
#SMDMethod
public List<StateTable> getStateTables(#SMDMethodParameter(name="countryId")Long countryId) {
stateTables = sharableService.findStatesByCountryId(countryId);
return stateTables;
}
#Action(value = "testJsonAction",
results = {
#Result(name = ActionSupport.SUCCESS, type = "json", params = {"enableSMD", "true"})},
interceptorRefs = {
#InterceptorRef(value = "json", params = {"enableSMD", "true", "includeProperties", "result\\[\\d+\\]\\.stateId, result\\[\\d+\\]\\.stateName", "excludeNullProperties", "true"})})
public String executeAction() throws Exception {
return SUCCESS;
}
#Action(value = "Test",
results = {
#Result(name = ActionSupport.SUCCESS, location = "Test.jsp"),
#Result(name = ActionSupport.INPUT, location = "Test.jsp")},
interceptorRefs = {
#InterceptorRef(value = "defaultStack", params = {"params.acceptParamNames", "", "params.excludeMethods", "load", "validation.validateAnnotatedMethodOnly", "true"})})
public String load() throws Exception {
//This method is just used to return an initial view on page load.
return ActionSupport.SUCCESS;
}
}
This method causes a list of states corresponding to the countryId supplied by the jQuery function as a parameter to this method to be returned which is delegated to the jQuery function as a JSON response.
This works fine unless Spring Security comes into picture. While using Spring Security, the request is forbidden.
The header information can be viewed as follows.
Request URL:http://localhost:8080/TestStruts/admin_side/testJsonAction.action
Request Method:POST
Status Code:403 Forbidden
Request Headers
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:73
Content-Type:application/json-rpc; charset=UTF-8
Cookie:JSESSIONID=0C4D7DFD269F1D5F7315A39971A75961; sbOverlayID=42887237
Host:localhost:8080
Origin:http://localhost:8080
Referer:http://localhost:8080/TestStruts/admin_side/Test.action
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36
X-Requested-With:XMLHttpRequest
Request Payload
{jsonrpc:2.0, method:getStateTables, id:jsonrpc, params:[2]}
id: "jsonrpc"
jsonrpc: "2.0"
method: "getStateTables"
params: [2]
Response Headers
Content-Length:1149
Content-Type:text/html;charset=utf-8
Date:Tue, 28 Jan 2014 22:12:55 GMT
Server:Apache-Coyote/1.1
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
My Spring Security configurations are exactly the same as mentioned in this question.
Where to look into Spring Security?
Found something. It is because I'm using a CSRF token (configured in the spring-security.xml file as <csrf/>) which is required to be sent along with the AJAX request. it worked, when I used a jQuery function along with <meta> tags as mentioned here.
If you using JSON, then it is not possible to submit the CSRF token
within an HTTP parameter. Instead you can submit the token within a
HTTP header. A typical pattern would be to include the CSRF token
within your meta tags. An example with a JSP is shown below:
<html>
<head>
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
<!-- ... -->
</head>
<!-- ... -->
You can then include the token within all your Ajax requests. If you
were using jQuery, this could be done with the following:
$(function () {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});