WCF service hosed in application can't be accessed from javascript? - javascript

I have an console application which starts a WCF service, and I want to access it in an html file using javascript.
Don't want to use web.config because it seems too complicated. and I want to host the service in an addon of an application later. (but if web.config meets my requirement, it is ok to use it too).
Following is the service code:
class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8080");
using (ServiceHost host = new ServiceHost(typeof(HelloWorldService), baseAddress))
{
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
host.AddServiceEndpoint(typeof(IHelloWorldService), new BasicHttpBinding(), "bh");
host.AddServiceEndpoint(typeof(IHelloWorldService), new WebHttpBinding(WebHttpSecurityMode.None), "wb");
host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
host.Close();
}
}
}
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
[WebGet(UriTemplate = "/SayHello?name={name}", ResponseFormat = WebMessageFormat.Json)]
string SayHello(string name);
}
public class HelloWorldService : IHelloWorldService
{
public string SayHello(string name)
{
Console.WriteLine("called SayHello");
return string.Format("Hello, {0}", name);
}
}
And I want to access the service using javascript from a single html file, e.g. index.html like this:
jQuery.post("http://localhost:8080/HelloWorldService.svc/wb/SayHello", {name:"kii"}, function(ret){alert(ret);}});
Or like this:
jQuery.get("http://localhost:8080/HelloWorldService.svc/wb/SayHello?name=kii", function(ret){alert(ret);}});
But they don't work.
"POST" method got "404 Not Found"
and
"GET" method got "405 Method Not Allowed"
Any suggestion?
thanks very much~~

here is the modified program for your reference.
class Program {
static void Main(string[] args) {
Uri baseAddress = new Uri("http://localhost:8080");
using (ServiceHost host = new ServiceHost(
typeof(HelloWorldService), baseAddress)) {
host.Description.Behaviors.Add(
new ServiceMetadataBehavior { HttpGetEnabled = true });
host.AddServiceEndpoint(
typeof(IHelloWorldService), new BasicHttpBinding(), "bh");
var webEndPoint = host.AddServiceEndpoint(
typeof(IHelloWorldService),
new WebHttpBinding(WebHttpSecurityMode.None), "wb");
webEndPoint.Behaviors.Add(new WebHttpBehavior());
host.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
host.Open();
var n = 0;
foreach (var endPoint in host.Description.Endpoints) {
Console.WriteLine("endpoint " + n);
Console.WriteLine(" address: " + endPoint.Address);
Console.WriteLine(" absolute path: " + endPoint.ListenUri.AbsolutePath);
Console.WriteLine(" absolute uri: " + endPoint.ListenUri.AbsoluteUri);
n++;
}
Console.WriteLine();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
}
}
}
The only actual difference is to add WebHttpBehavior into the web endpoint.
running this program, and open brower to test address localhost:8080/wb/sayhello?name=abc
if the brower returns "abc", that means the web end point is working.
if calling this address by jQuery is still not working, then trouble-shooting on jQuery side.

Related

Spring #ExceptionHandler does not render view if webapp is restarted in the background

I'm dealing with a HttpSessionRequiredException and read about (https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc) how to catch it via the #ExceptionHandling annotation.
This does work since my breakpoint hits the spot. Unfortunately the string containing the view name does not trigger any view resolving and therefore no error page is being rendered.
Steps to Reproduce:
Open http://localhost:8080/manager (Session Attributes are being initialized)
Restart Web Application (Session/SessionAttributes are being reset)
Fill out form and press button (launches POST Request via AJAX - see Edit #2)
ExceptionHandler jumps in. Since a HttpSessionRequiredException is being thrown due the missing session attributes
Check Network Panel in Chrome which yields following information on the failed POST:
Controller Class incl. Exception Handler
#Controller
#Log
#RequestMapping(value = "/manager")
#SessionAttributes({"moduleDescriptors", "Environments", "moduleExecutionData"})
public class ManagerController {
private static final String MANAGER_VIEW = "manager";
private final ManagerHelper managerHelper;
private final ModuleExecution moduleExecution;
private final SystemProperties SystemProperties;
#Autowired
public ManagerController(ManagerHelper managerHelper, ModuleExecution moduleExecution,
SystemProperties SystemProperties) {
this.managerHelper = managerHelper;
this.moduleExecution = moduleExecution;
this.SystemProperties = SystemProperties;
}
#GetMapping
public ModelAndView render() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName(MANAGER_VIEW);
modelAndView.addObject("moduleExecutionData", new ModuleExecutionData());
List<ModuleDescriptor> moduleDescriptorsFromServices = managerHelper.getModuleDescriptorsFromServices();
modelAndView.addObject("moduleDescriptors", moduleDescriptorsFromServices);
//TODO: Change varName for Systems
modelAndView.addObject("Environments", SystemProperties.getEnvironments());
log.info("Found " + moduleDescriptorsFromServices.size() + " module descriptors");
return modelAndView;
}
#PostMapping
public String execute(#ModelAttribute ModuleExecutionData moduleExecutionData) {
moduleExecution.execute(moduleExecutionData);
// sessionStatus.setComplete();
return MANAGER_VIEW;
}
#ExceptionHandler(HttpSessionRequiredException.class)
public String sessionError(){
return "sessionError";
}
}
My view lies within all the folder with all working views.
Any idea what I'm doing wrong? I'm configuring spring completely with annotations - not XML.
Edit:
I checked the response and saw that it actually returns the HTML of the View. But this HTML is not rendered. Is it because I made a POST request? Which actually ignores any return HTML?
But that does not make sense - because my original PostHandler does return a view as well and it is rendered.
PostHandler
#PostMapping
public String execute(#ModelAttribute ModuleExecutionData moduleExecutionData) {
moduleExecution.execute(moduleExecutionData);
return MANAGER_VIEW;
}
Edit #2
Here is the POST JavaScript Ajax logic
function postForm(event) {
const moduleId = $(event.currentTarget).data("module-id");
const formData = $("#" + moduleId).serialize();
$.ajax({
type: "post",
data: formData,
url: "/manager",
dataType: "json"
});
}

New-PSSession is not returning a session to import and use

I'm probably doing this the wrong way and should use WSManConnectionInfo instead somehow but a lot of examples I've found point to this method of creating a new PowerShell Session in a C# app under different credentials as valid method.
I'm stuck with the piece that invokes the New-PSSession as it does not return a session object (returns an empty collection) that I can use in the next set of commands. My goal is to create a C# function that takes in a PowerShell script block and runs it with admin credentials.
(UPDATE) The code below now works. Be sure to check "Enable-WSManCredSSP" params for the client machine name or it will fail to delegate credentials when creating a new PSSession. I changed the code to use the local machine name for the client versus * for all on the domain, I believe using * is a bad security practice.
public static IEnumerable<PSObject> RunScriptBlock(string block)
{
var nc = Domains.Default.GetNetworkCredential();
var creds = new PSCredential(nc.Domain + "\\" + nc.UserName, nc.SecurePassword);
using (Runspace rs = RunspaceFactory.CreateRunspace())
{
rs.Open();
using (var psh = PowerShell.Create())
{
psh.Runspace = rs;
PSSession session = null;
try
{
psh.AddCommand("Enable-WSManCredSSP");
psh.AddParameter("Role", "Client");
psh.AddParameter("DelegateComputer", Environment.MachineName + ".mydomain.com");
psh.AddParameter("Force", true);
psh.Invoke();
psh.Commands.Clear();
psh.AddCommand("Enable-WSManCredSSP");
psh.AddParameter("Role", "Server");
psh.AddParameter("Force", true);
psh.Invoke();
psh.Commands.Clear();
psh.AddCommand("New-PSSession");
psh.AddParameter("Credential", creds);
psh.AddParameter("Authentication", "Credssp");
session = psh.Invoke()[0].BaseObject as PSSession;
psh.Commands.Clear();
psh.Runspace.SessionStateProxy.SetVariable("", "");
psh.AddCommand("Invoke-Command");
psh.AddParameter("Session", session);
ScriptBlock sb = new RunspaceInvoke().Invoke("{ " + block + " }")[0].BaseObject as ScriptBlock;
psh.AddParameter("ScriptBlock", sb);
var results = psh.Invoke();
//if (results.HasErrors)
//{
//}
return results;
}
catch (Exception)
{
return null;
}
finally
{
psh.Commands.Clear();
psh.AddCommand("Remove-PSSession");
psh.AddParameter("Session", session);
psh.Invoke();
rs.Close();
}
}
}
}

Wicket AbstractDefaultAjaxBehavior do recursive update the page

I have some ajax Behaviour that should pick some data using JS, and turn it back to Java. Sometimes it works but quite ofen it is just add url parameter and do page refresing/
public abstract class LoggedVKIdBehaviour extends AbstractDefaultAjaxBehavior {
private static final Logger logger = LoggerFactory.getLogger(LoggedVKIdBehaviour.class);
#Override
protected void respond(AjaxRequestTarget target) {
String loggedVkId = RequestCycle.get().getRequest().getRequestParameters().getParameterValue("logged_vkid").toString();
logger.info("ajax has comming with logged VK ID " + loggedVkId);
recived(target, loggedVkId);
}
protected abstract void recived(AjaxRequestTarget target, String loggedVkId);
#Override
public void renderHead(final Component component, IHeaderResponse response) {
super.renderHead(component, response);
Map<String, Object> map = new HashMap<>();
map.put("callbackFunction", getCallbackFunction(CallbackParameter.explicit("logged_vkid")));
//
PackageTextTemplate ptt = new PackageTextTemplate(LoggedVKIdBehaviour.class, "vkid_callback.js");
OnDomReadyHeaderItem onDomReadyHeaderItem = OnDomReadyHeaderItem.forScript(ptt.asString(map));
response.render(onDomReadyHeaderItem);
}
}
js template
var calback = ${callbackFunction};
var logged_vk_id = 11;
function authInfo(response) {
if (response.session) {
logged_vk_id = response.session.mid;
calback(response.session.mid);
console.log("recived callback from VK " + logged_vk_id);
}
}
$(document).ready(function () {
VK.Auth.getLoginStatus(authInfo);
});
it is do recursive redirection like http://localhost:8080/mytool/product/1?logged_vkid=332797331&logged_vkid=332797331&logged_vkid=332797331&logged_vkid=332797331&logged_vkid=332773...
As i understand Ajaj technology - iti asynchronus requests, that shouldn't touch main url at all. So what is the reason for page refreshing?
this is generated Callback function
function (logged_vkid) {
var attrs = {"u":"../wicket/bookmarkable/com.tac.kulik.pages.product.ProductPage?12-1.IBehaviorListener.0-&productID=1"};
var params = [{"name":"logged_vkid","value":logged_vkid}];
attrs.ep = params.concat(attrs.ep || []);
Wicket.Ajax.ajax(attrs);
}
I use wicket 7.2
I did a lot investigations for few days. And found that when i remove
setPageManagerProvider(new NoSerializationPageManagerProvider(this));
Application throw me exepton in polite logs
org.apache.wicket.WicketRuntimeException: A problem occurred while
trying to collect debug information about not serializable object look
like it is could come from aused by: java.io.NotSerializableException:
com.tac.kulik.panel.smaccounts.SMAccountsPanel$1
which means that page tryed to be serialized for SOME REASON but $1 it is mean Anonimous class. I had few class created anonimously to ges some ajax links coming from ListView to be managed on parent panel. So After removing this Anonimous class logic, everything start and run well.
So i am happy, but still don't understand which reason page did serialization after ajax, and what the reason was to refresh whole page.

how to send a javascript Object from one Client to Another by SignalR

I am working on a Javascript multiplayer game and I need to send a Javascript object from one client to another client using signalR. Till now I am sending client to client data by string or array.
But I don't know how to receive Javascript object in server for sending that object to another client.
var MyInfo = {
UserName: loginUserName,
userid: logInUserId,
getinfo: function() {
return this.UserName + ' ' + this.userid;
}
}
Which data type shall I use to receive that Javascript data in my hub.
I am working on C# .NET MVC.
I got the answer of my problem...
C# language provides automatically conversion of Javascript object to Object data type. Thus I send the Javascript object to server and then receive that object in Object datatype. After that I send that object to destination client, as follow:
var MyInfo = {
UserName: loginUserName,
userid: logInUserId,
getinfo: function() {
return this.UserName + ' ' + this.userid;
}
};
var MyInfo2 = {
UserName: "",
userid: "",
getinfo: function() {
return this.UserName + ' ' + this.userid;
}
};
var chessR = $.connection.gameHub;
var myConnectionID;
chessR.client.testObject = function(temp) {
MyInfo2.UserName = temp.UserName;
MyInfo2.userid = temp.userid;
alert(MyInfo2.getinfo());
}
$.connection.hub.start().done(function() {
chessR.server.testObject(MyInfo);
});
On signalR hub I write:
public class GameHub : Hub
{
public void testObject(Object MyInfo)
{
Clients.Caller.testObject(MyInfo);
}
}
Now the problem solved.
I think the easy way to go would be creating a MyInfoModel on the server side containing the same properties of the JS model and simply pass it on the server method.
Normally, SignalR and ASP.NET should handle the serialization of your data, letting you to send and recieve complex objects. (Please note that I have not tested it, it is just an educated guess). Since you can easily send complex objects from the server to the client, I see no reason why you cannot send them from the client to the server.
If the first approach (creating the model on the server and make the server method accept a model) doesn't work, you can serialize the object, send it as a string and deserialize it on the hub (you still need the model to deserialize).
If neither of these work, leave a message and when I get to a computer with VS I will test them and share the results.
Hope this helps! Good luck!
Your solution is good for sending the object between JS clients, but if you want to use the object on the C# base Server or get some typing (usually ideal), then you can create a C# model that matches the JS object.
And depending on the signalr Json serialize casing options you use, you can use attributes to specify how the C# object should be de/serialized:
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
public class MyInfoModel
{
[Required]
[JsonPropertyName("userId")]
public string UserId { get; set; }
[Required]
[JsonPropertyName("userName")]
public string UserName { get; set; }
}
JS client side (in typescript)
type UserInfo = {
userName: string;
userId: string;
};
const myInfo: UserInfo = {
userName: loginUserName,
userId: logInUserId,
};
await $.hubConnection.send("HubMethodWithTypedParam", myInfo);
Now the hub method can be declared with a typed parameter like this:
public class GameHub : Hub
{
public void HubMethodWithTypedParam(MyInfoModel myInfo)
{
...
}
}

GCM Push notification if App is closed in mobile (Phonegap Android)

I am using GCM with my phonegap android app. The problem I am facing is, the app is able to receive the notification if its open in mobile, but not able to receive notification if its closed. I have gone through the java code written is working fine. But its not able to communicate with javascript code written for receiving message
public class GCMIntentService extends GCMBaseIntentService {
public static final String ME="GCMReceiver";
public GCMIntentService() {
super("GCMIntentService");
}
private static final String TAG = "GCMIntentService";
#Override
public void onRegistered(Context context, String regId) {
Log.v(ME + ":onRegistered", "Registration ID arrived!");
Log.v(ME + ":onRegistered", regId);
JSONObject json;
try
{
json = new JSONObject().put("event", "registered");
json.put("regid", regId);
Log.v(ME + ":onRegisterd", json.toString());
// In this case this is the registration ID
GCMPlugin.sendJavascript( json );
}
catch( JSONException e)
{
// No message to the user is sent, JSON failed
Log.e(ME + ":onRegisterd", "JSON exception");
}
}
#Override
public void onUnregistered(Context context, String regId) {
Log.d(TAG, "onUnregistered - regId: " + regId);
}
#Override
protected void onMessage(Context context, Intent intent) {
Log.d(TAG, "onMessage - context: " + context);
// Extract the payload from the message
Bundle extras = intent.getExtras();
if (extras != null) {
try
{
Log.v(ME + ":onMessage extras ", extras.getString("message"));
JSONObject json;
json = new JSONObject().put("event", "message");
json.put("message", extras.getString("message"));
json.put("msgcnt", extras.getString("msgcnt"));
Log.v(ME + ":onMessage ", json.toString());
GCMPlugin.sendJavascript( json );
// Send the MESSAGE to the Javascript application
}
catch( JSONException e)
{
Log.e(ME + ":onMessage", "JSON exception");
}
}
}
#Override
public void onError(Context context, String errorId) {
Log.e(TAG, "onError - errorId: " + errorId);
}
}
I think you are using GCMPlugin plugin.There is nowhere written anything how to handle push notifications when the app will go background or being destroyed.In my opinion its better to remove this plugin and use PushPlugin ,otherwise you have to make a drastic change not only to the GCMIntentservice.java but also to the GCMPlugin.java.

Categories