Odata with Asp.net and angularjs - javascript

I am following up in the course AngularJS Front to Back with Web API using ASP.net, we are trying to do queries using ODATA so i added this code in the ProductController in the WebAPI
// GET: api/Products
[EnableQuery()]
public IQueryable<Product> Get()
{
var productRepository = new ProductRepository();
return productRepository.Retrieve().AsQueryable();
}
then added the below code in the productcontroller in the angular code:
function ProductListCtrl(productResource) {
var vm = this;
productResource.query({$skip:1, $top:3}, function (data) {
vm.products = data;
})
but when I try to run it gives me the below error:
angular.js:12701 GET http://localhost:59302//api/products?$skip=1&$top=3 400 (Bad Request)
Possibly unhandled rejection: {"data":{"message":"The query specified in the URI is not valid. No non-OData HTTP route registered.","exceptionMessage":"No non-OData HTTP route registered.",.....

Maybe you don't have odataConfiguration?? Where's you EDM configuration?
In your config file you need something like that:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code:
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: builder.GetEdmModel());
}
}

Related

Spring Boot Websocket with SockJS and StompJS connect function does not work, always error

I try to build a chat application with HTML,JS,CSS with the libraries STOMPJS and SOCKJS as the frontend and Spring Boot as backend.
My connect code in the frontend looks like this:
function connect() {
var socket = new SockJS("http://localhost:8080/chat");
stompClient = Stomp.over(socket);
stompClient.connect(
{},
function (frame) {
console.log("2");
setConnected(true);
console.log("Connected: " + frame);
stompClient.subscribe("/topic/messages", function (messageOutput) {
showMessageOutput(JSON.parse(messageOutput.body));
});
},
console.log("error")
);
}
As far as I know is the connect function of STOMPJS like this: headers, connectCallback, errorCallback.
It never reach the console.log "2" and it gives me the console.log "error" back.
I activated CORS like this in my backend with setAllowedOriginPatterns("*") in my Spring Boot application:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat");
registry.addEndpoint("/chat").setAllowedOriginPatterns("*").withSockJS();
}
}
And the controller looks like this:
#Controller
public class MController {
#MessageMapping("/chat")
#SendTo("/topic/messages")
public OutputMessage send(Message message) throws Exception {
String time = new SimpleDateFormat("HH:mm").format(new Date());
return new OutputMessage(message.getFrom(), message.getText(), time);
}
}
In the screenshot you can see the console.log when I execute the function "connect":
I checked all the documentation of SockJS and StompJS but I couldn't find a solution.
Thank you very much for your answer in advance. :)

403 (Forbidden) response from SignalR Hub using ASP.NET hosting on IIS server

I'm hosting a SignalR Hub on Windows Server 2012 with IIS as an ASP.NET Web application that I've tested successfully on my local machine. But when I publish and try to connect from a Angular application the server responds with 403 Forbidden on the /negotiate request. The Angular application is located on a different domain then the Hub server.
I've read that this is caused by a CORS issue, but I've tried every solution I can find without any change. Can it be a IIS server issue or have I missed something in my code?
The route being called is https://example.com/signalr/negotiate
SignalR Server:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
EnableJSONP = true,
EnableDetailedErrors = true
};
map.RunSignalR(hubConfiguration);
});
}
}
// Hub that handles Online user list
public class OnlineHub : Hub
{
private static List<AppUserDto> _usersOnline = new List<AppUserDto>();
public OnlineHub()
{
// Automapper Setup
MappingConfig.Init();
}
public override Task OnConnected()
{
var user = GetUser();
_usersOnline.Add(user);
Clients.All.listUpdated(_usersOnline);
return base.OnConnected();
}
public override Task OnReconnected()
{
var user = GetUser();
// Add user to list of online users if it doesn't exist
if (!_usersOnline.Any(u => u.Email == user.Email))
{
_usersOnline.Add(user);
Clients.All.listUpdated(_usersOnline);
}
return base.OnReconnected();
}
public override Task OnDisconnected(bool stopCalled)
{
var user = GetUser();
if (!_usersOnline.Any(u => u.Email == user.Email))
{
// Remove user from list of online users
_usersOnline.Remove(user);
Clients.All.listUpdated(_usersOnline);
}
return base.OnDisconnected(stopCalled);
}
private AppUserDto GetUser()
{
using (var db = new EntityDbContext())
{
// Get connected AppUserDto
var user = db.AppUsers.FirstOrDefault(u => u.UserName == Context.User.Identity.Name);
// Add user to list of online users
if (user != null)
{
return Mapper.Map<AppUserDto>(user);
}
return null;
}
}
}
Angular Application SignalR Service
import { AppSettings } from './../app.settings';
import { EventEmitter, Injectable } from '#angular/core';
declare const $: any;
#Injectable()
export class SignalRService {
// Declare the variables
private proxy: any;
private connection: any;
private authData: any;
// create the Event Emitter
public messageReceived: EventEmitter<any>;
public connectionEstablished: EventEmitter<Boolean>;
public connectionExists: Boolean;
constructor(private appSettings: AppSettings) {
// Setup
this.connectionEstablished = new EventEmitter<Boolean>();
this.messageReceived = new EventEmitter<any>();
this.connectionExists = false;
}
public initialize(proxyName: string): void {
this.connection = $.hubConnection(this.appSettings.SIGNALR_BASE_URL);
this.proxy = this.connection.createHubProxy(proxyName);
this.registerOnServerEvents();
this.startConnection();
}
private startConnection(): void {
this.connection.start({withCredentials: false})
.done((data: any) => {
console.log('SignalR Connected with: ' + data.transport.name);
this.connectionEstablished.emit(true);
this.connectionExists = true;
})
.fail((error: any) => {
console.log('SignalR could not connect: ' + error);
this.connectionEstablished.emit(false);
});
}
private registerOnServerEvents() {
this.proxy.on('listUpdated', (list: any) => {
console.log(list);
this.messageReceived.emit(list);
});
}
}
initialize(proxyName) gets called from a controller to start a connection to the Hub.
UPDATE
I've tried to rebuild the server and Hub using .NET Core 2.0, but when I test that on the IIS server I get:
"Failed to load https://signalr.example.com/online/negotiate: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://example.com' is therefore not allowed access."
So it's still a CORS issue even though I've setup everything just as multiple guides have done.
I've had issues in the past where the api path you are trying to hit is actually a virtual directory, and then IIS returns you a 403 because it thinks you are trying to view / access that directory instead of the webAPI route.
GET api/negotiate will 403 if you have the directory api/negotiate on your server.
This will be the case if you WebApiController is located in your project in a directory like:
/api/negotiate/NegotiateApiController.cs
You can resolve this very easily if that's the case by either changing the route or the directory name.
Note: This will come back as a 405 on some browsers.

Angularjs, JavaEE and http request with inherited objects?

I work on webapp and can't find solution or example of my problem.
I use AngularJS, RestServis and JavaEE . My problem is how to send inherited object with superObject
In java I have two classes:
public class User{
protected String userName;
protected String userSurename;
..
..
}
Second class is a subclass
public class Worker extends User{
protected int idWorker;
protected String position;
..
..
}
in Angular controller I have
$scope.user = {
userName : "jon" ,
userSurename :"dep" }
$scope.worker= {
idWorker: 88 ,
position: "seller" }
and I use http protocol to send data on server side like this
this.saveWorker = function(worker) {
return $http({
method:'post',
url:this.apiBasicUrl,
contentType: "application/json",
data: worker
});
};
How in Angular in data to put one object and on Java side get worker object with user data also ? Can I , object like in java , make in angular with inherited ?
On Angular side, I suggest using $resource for communication with REST API:
var Worker = $resource('/worker/:workerId', {workerId:'#id'});
//get
var worker = Worker.get({workerId:123}, function() {
worker.abc = true;
//save
worker.$save();
});
On server side you should have a REST endpoint that is supposed to pick up these objects:
#Path("/worker")
public class WorkerService {
#GET
#Path("{workerId}")
public Worker getWorker(#PathParm("workerId") Integer workerId) {
//implement
}
#POST
public void saveWorker(Worker worker) {
//implement
}
}
This might not work out of the box. You will most likely need Jackson provider to enable REST to "translate" JSON into Java objects.
See this example: http://www.mkyong.com/webservices/jax-rs/json-example-with-jersey-jackson/

Metadata query failed for: Breeze JS

I was developing Breeze JS To Dos app using ASP.net Web Api. When I request to the resource I'm getting "Metadata query failed for: odata/Todos/Metadata; NaN". But when I manually request to /odata/Todos/Metadata it works fine. Do you have any idea bout this?
Try:
var dataService = new breeze.DataService({
serviceName: "http://localhost:2099/api/yourcontent/",
hasServerMetadata: false,
});
var manager = new breeze.EntityManager({ dataService: dataService });
I found the MaxDataServiceVersion header from datajs to cause 404s...
Try
var oldClient = OData.defaultHttpClient;
var myClient = {
request: function (request, success, error) {
delete request.headers.MaxDataServiceVersion;
return oldClient.request(request, success, error);
}
};
OData.defaultHttpClient = myClient;

Invalid web service call, missing value for parameter with Backbone and Webservice webmethods

Is it possible for backbone to interface with asp.net soap webservice methods for saving and retrieving the data? because i got this error from the webmethod but actually the POST contains the parameters.
Server Side
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static Dummy SaveDummy(Dummy myDummy)
{
Dummy dumdum = myDummy;
HttpContext.Current.Session["data"] = dumdum;
return myDummy;
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public static Dummy FetchDummy()
{
return (Dummy)HttpContext.Current.Session["data"];
}
public class Dummy
{
private string _name;
private string _script;
public string Name
{
get { return _name; }
set { _name = value; }
}
public string Script
{
get
{
return _script;
}
set { _script = value; }
}
}
Backbone Model
window["model"] = Backbone.Model.extend({
initialize: function () {
console.log("CREATED");
},
defaults:{
name:"Please enter your name",
script:"Hello World"
},
urlRoot: "index.aspx/SaveDummy",
validate: function (attrs) {
}
});
Application
$("document").ready(function () {
var myModel = new model({
name: "Stack Overflow",
script: "alert('Hi SO')"
});
var myView = new view({
model: myModel,
el: $("#placeholder")
});
console.log("SAVING");
myModel.save();
console.log("FETCHING");
myModel.fetch();
POST
{"name":"Stack Overflow","script":"alert('Hi SO')"}
Message
Invalid web service call, missing value for parameter: 'myDummy'.
Note
I did look into other posts with similar problem, which were solved by doing something like
{myDummy={"name":"Stack Overflow","script":"alert('Hi SO')"}} . How could this be generated using Backbone?
All of the server-side synchronization in Backbone is handled through Backbone.Sync which is designed for two things:
REST apis that work with JSON (not SOAP/XML)
Extensibility
So you will need to override the Backbone.Sync behavior to talk to your backend. It appears to be relatively straight-forward. Some guidance can be found in these links:
SO post about overriding Backbone.Sync
Blog post about consuming XML services in Backbone

Categories

Resources