Pass data from ASP.NET Webmethod to Angular 2 - asp.net

Hello Stackoverflowers,
Apologies if this is duplicate, I really tried to find a simple answer for this, but I couldn't.
I need to pass some data from ASP.NET Webmethod to my Angular 2 class.
I'm starting off with a very simple string "hello".
How can I use the server side Get() method to populate the value value ?
My .NET server side code:
[WebMethod]
public static string Get()
{
return "Hello Koby";
}
My Angular 2 code (Very simplified):
import {Component} from 'angular2/core';
import {Injectable} from 'angular2/core';
import {HTTP_PROVIDERS, Http, Response, Headers, RequestOptions} from 'angular2/http';
#Component({
selector: 'log',
templateUrl: '/Scripts/Angular2/templates/log.html'
})
export class Log {
private http;
value = ? // <----- This should come from the server
}
Being new to Angular 2, I can accept solutions, workarounds or curse words.
Thanks.

Related

HOCs, Context API and Next Pages

Its possible to use Hoc with context api inside a next page?
I have a next page generated by SSR, and a HOC privateRoute to validate authorization on this page. But for every access, we have a authorization request and its sound's me like a problem.
My idea is to use contexApi to get data one time, and reuse that on auth private route.
Anyone has a minimal exemple about?
Thanks.
I found a solution.
The problem was to use Context inside react class component.
mport React, { Component } from 'react'
import UserContext from './UserContext'
class HomePage extends Component {
static contextType = UserContext
componentDidMount() {
const user = this.context
console.log(user) // { name: 'Tania', loggedIn: true }
}
for more, see https://www.taniarascia.com/using-context-api-in-react/
render() {
return <div>{user.name}</div>
}
}

Could using #angular/http and #angular/common/http at the same time cause problems in an Angular ASP.NET application?

When I import:
import { HttpClientModule } from '#angular/common/http';
import { HttpModule } from '#angular/http';
And then:
constructor(private http: Http, private httpClient: HttpClient) {}
this.httpClient.post(...
this.http.post(...
In this case, I use Microsoft Identity, which relies on cookies for authentication.
Could that cause problems if I post, for example, the login in one way and the register in another?
Why do you want to use old, deprecated Http when you can use HttpClient?
Difference between HTTP and HTTPClient in angular 4?

How to define global variables in Angular 2 in a way that I can use them for property binding in templates?

In my Angular 2 (beta 14) application I need to keep track of user login status in order to hide/display certain elements.
The issue I'm getting is that property binding is not working the way I did as follows.
I created a class to store and update global variables:
app-global.ts
import {Injectable} from "angular2/core";
#Injectable() export class AppGlobals {
// use this property for property binding
public isUserLoggedIn: boolean = false;
setLoginStatus(isLoggedIn){
this.isUserLoggedIn = isLoggedIn;
}
getLoginStatus(){
return this.isUserLoggedIn;
} }
In the login component I import AppGlobals
export class LoginComponent {
constructor(private _appGlobals: AppGlobals) { }
and set login state by
this._appGlobals.setLoginStatus(true);
In another component I inject AppGlobals as I do in LoginComponent
I define a class (component)'s property
isLoggedIn: boolean = this._appGlobals.isUserLoggedIn; // I also tried by using the getter instead of the public property (see above)
which I then use in the component's template to show/hide a certain element:
<!-- here I also tried with {{!isLoggedIn}} but results in a syntax error whereas using [(hidden)] instead of [hidden] changes nothing -->
<div id="some-element" [hidden] = "!isLoggedIn">
Finally, the binding works but there is no update (this component is part of AppComponent template and shown in every page) when another component (e.g. LoginComponent) sets the login status.
EDIT I tried to apply Gunter's answer but I get the following errors:
app/app-globals.ts(10,54): error TS2346: Supplied parameters do not match any signature of call target.
app/app-globals.ts(13,29): error TS2339: Property 'emit' does not exist on type 'BehaviorSubject<boolean>'.
Error at line 10 comes from [SOLVED]
public isUserLoggedIn:BehaviorSubject = new BehaviorSubject().startWith(false);
and it's apparently caused by BehaviorSubject expecting 1 parameter
Error at line 13 comes from
this.isUserLoggedIn.emit(isLoggedIn);
and it's apparently cause by a non-existing emit method.
Also, I don't understand how shall I use AppGlobals so that the property binding auto updates in another component (see last example before EDIT)
Further, in LoginComponent I replaced isLoggedIn boolean type with BehaviorSubject because isUserLoggedIn has type BehaviorSubject in AppGlobals
but
this._appGlobals.isUserLoggedIn.subscribe(value => this.isLoggedIn = value);
returns a TypeError:
Assigned expression type boolean is not assignable to type BehaviorSubject
isLoggedIn: boolean = this._appGlobals.isUserLoggedIn;
is a one-time action that copies the value at the time when this line is executed. If you want subsequent changes to be propagated use observables
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/share';
import 'rxjs/add/operator/startWith';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
#Injectable()
export class AppGlobals {
// use this property for property binding
public isUserLoggedIn:BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
setLoginStatus(isLoggedIn){
this.isUserLoggedIn.next(isLoggedIn);
}
}
and use it like:
export class LoginComponent {
constructor(private _appGlobals: AppGlobals) {
this._appGlobals.isUserLoggedIn.subscribe(value => this.isLoggedIn = value);
}
See also https://stackoverflow.com/a/35568924/217408
had a similar need, ended up implementing this via simple getter - and it binds the property in the template (--> changes propagate). less code.
you can set the global var either directly or implement setters/getters in the Globals class.
globals.ts
export class Globals{
public static server_call_in_progress:boolean = true;
}
app.component.ts
import {Globals} from "./shared/globals";
export class AppComponent{
constructor(){}
ngOnInit(){}
get server_call_in_progress(){
return Globals.server_call_in_progress;
}
}
app.component.html
<div *ngIf="server_call_in_progress">
<div class="loader"></div>
</div>

Is Spring Boot + Spring MVC + Ratpack possible?

We're a Spring Boot shop and rely heavily on Spring MVC for our REST endpoints. We use Boot and embedded Tomcat to create a self-hosting JAR. Is it possible to replace Tomcat with Ratback while still keeping all my Spring MVC code in place? I am afraid that Spring MVC is tied into the servlet specification somehow and will not run without a servlet container. I am aware of dsyer/spring-boot-ratpack work but after skimming the code couldn't decide if Spring MVC would play well using the bridge. Is anyone aware of any work that will allow us to retain our investment in Spring MVC and have Spring Boot use Ratpack to manage HTTP traffic?
I suspect the crux of your question can be distilled to: "can we put our Spring controllers on top of Ratpack's non-blocking HTTP layer?" and the simplest answer to that question is no, for reason that the MVC programming model doesn't fit well into the reactive/NIO model very well.
However, if your application has followed some common model-view-controller-(and service) patterns, then your controllers should really just be performing data binding and parsing and delegating out to a service layer. If that's the case, then likely the code in your controller is already non-blocking, and you could easily translate it to Ratpack code.
As an example, consider the following #RestController in a Spring Boot app:
#RestController
#RequestMapping("/user")
class UserController {
#Autowired
UserService userService
#RequestMapping(method = RequestMethod.POST)
Long create(#RequestBody #Valid User user) {
User savedUser = userService.save(user)
return savedUser.id
}
}
Spring's data binding aspect is a computation process (ie isn't I/O bound), so we can easily translate this into a Ratpack handler:
import app.SpringConfig
import app.User
import app.UserService
import org.springframework.boot.SpringApplication
import org.springframework.context.ApplicationContext
import ratpack.jackson.JacksonModule
import static ratpack.groovy.Groovy.ratpack
import static ratpack.jackson.Jackson.fromJson
import static ratpack.jackson.Jackson.json
import static ratpack.spring.Spring.spring
ratpack {
bindings {
add(new JacksonModule())
bindInstance(ApplicationContext, SpringApplication.run(SpringConfig))
}
handlers { ApplicationContext ctx ->
register(spring(ctx))
prefix("user") {
handler { UserService userService ->
byMethod {
post {
def user = parse(fromJson(User))
blocking {
userService.save(user)
} then { User savedUser ->
render(json(savedUser))
}
}
}
}
}
}
}
Where SpringConfig looks like this:
package app
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
#Configuration
class SpringConfig {
#Bean
UserService userService() {
new UserService()
}
}
And here's a functional test to prove it:
package app
import com.fasterxml.jackson.databind.ObjectMapper
import ratpack.groovy.test.GroovyRatpackMainApplicationUnderTest
import ratpack.test.ApplicationUnderTest
import ratpack.test.http.TestHttpClient
import spock.lang.Shared
import spock.lang.Specification
import static groovy.json.JsonOutput.toJson
class FuncSpec extends Specification {
#Shared ApplicationUnderTest aut = new GroovyRatpackMainApplicationUnderTest()
#Shared ObjectMapper mapper = new ObjectMapper()
#Delegate TestHttpClient client = aut.httpClient
def "should parse and save user"() {
given:
def user = new User(username: "dan", email: "danielpwoods#gmail.com")
when:
requestSpec { spec ->
spec.body { b ->
b.type("application/json")
b.text(toJson(user))
}
}
post('user')
then:
def savedUser = mapper.readValue(response.body.text, User)
and:
savedUser.id
}
}
Hope this helps!
The Spring MVC programming model is not very heavily dependent on Servlet APIs, but it's not supported in any other containers (i.e. not in Ratpack). There is some async stuff there now and Servlet 3.1 enhances it some more, so if that's the part of Ratpack that attracts you, maybe just using that would be a better approach. You won't get all the way to reactive and non-blocking IO that way though.

ModuleMessageInterceptor vs MessageInterceptor

I am developing an application in Flex using the cairngorm module library and Parsley.
Parsley documentation chapter 5 says: "Interceptors may come in handy when you want to decide whether or not the message should be passed to handlers".
When using the ModuleMessageInterceptor the above is not true. Which means that my MessageHandler receive the message before the MessageInterceptor.
Does anyone knows a work around?
Regards,
Fadi
The solution to this problem was extending the ModuleMessageInterceptor class as follows:
package fr.core.patch.cairngorm
{
import com.adobe.cairngorm.module.ModuleIdMetadata;
import com.adobe.cairngorm.module.ModuleMessageDispatcher;
import com.adobe.cairngorm.module.ModuleMessageInterceptor;
import com.adobe.cairngorm.module.ParsleyModuleMessage;
import flash.system.ApplicationDomain;
import org.spicefactory.lib.reflect.ClassInfo;
import org.spicefactory.lib.reflect.Property;
import org.spicefactory.parsley.core.registry.ObjectDefinitionRegistry;
import org.spicefactory.parsley.core.registry.RootObjectDefinition;
import org.spicefactory.parsley.tag.messaging.MessageHandlerDecorator;
import org.spicefactory.parsley.tag.messaging.MessageInterceptorDecorator;
public class ATPModuleMessageInterceptor extends ModuleMessageInterceptor
{
public function ATPModuleMessageInterceptor()
{
super();
}
public var order:int;
private var target:Property;
override public function process(registry:ObjectDefinitionRegistry):void
{
target=getModuleIdTargetProperty(registry.domain);
var interceptor:MessageInterceptorDecorator=new MessageInterceptorDecorator();
interceptor.type=type;
interceptor.selector=selector;
interceptor.method="interceptModuleMessage";
interceptor.order = order;
var messageHandler:MessageHandlerDecorator=new MessageHandlerDecorator();
messageHandler.type=ParsleyModuleMessage;
messageHandler.method="parsleyModuleMessageHandler";
var definition:RootObjectDefinition=registry.builders.forRootDefinition(ModuleMessageDispatcher).decorators([interceptor, messageHandler]).buildAndRegister();
definition.constructorArgs.addValue(target);
if (moduleRef)
{
definition.constructorArgs.addIdReference(moduleRef);
}
}
private function getModuleIdTargetProperty(domain:ApplicationDomain):Property
{
var props:Array=ClassInfo.forClass(type, domain).getProperties();
for each (var prop:Property in props)
{
if (prop.hasMetadata(ModuleIdMetadata))
{
return prop;
}
}
return null;
}
}
}
By doing the above we have added the order property to the ModuleMessageInterceptor which solve the problem I had.
Regards,
Fadi Mansour
In Parsley 2.4, MessageInterceptors have been depracated:
And ModuleMessageInterceptor is not a Parsley thing, it's a Cairngorm thing. Personally, I'd stay away of Cairngorm altogether because of my experience with it. After looking online, I saw that other people had similar issues. Your best bet is to post on the same forum and hopes somebody helps.

Resources