SignalR 2.0 Cross domain with console as a server side not working - cross-domain

Here my server-side code
class Program
{
static void Main(string[] args)
{
string url = "http://localhost:8080";
using (WebApp.Start<Startup>(url))
{
Console.WriteLine("Server running on {0}", url);
}
}
}
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
};
map.RunSignalR(hubConfiguration);
});
}
}
When I run the console app and browse 'http://localhost:8080/signalr/hubs' on the server, it's show some jQuery code But when I try to browse 'http://[server-ip]/signalr/hubs', it's show error 400 on both server and clients
Is this mean than my server-side app not allow cross domain yet?

Here the solutions :
change
string url = "http://localhost:8080";
to
string url = "http://+:8080";

Related

How to receive the ASPN Token in Xamarin Forms iOS-App

I followed this tutorial to implement Push-Notifications in my Xamarin-Forms App (especially the iOS part). Now my problem is, when I press the register-button, I get the error message "Unable to resolve token for APNS".
Stepping through the code in debug mode I could verify, that the Token property in DeviceInstallationService is indeed null.
So I've gone one step back, and identified that the Token is set only via RegisteredForRemoteNotification in AppDelegate.cs, but this method is never called when I run the App.
Here is some code: App-Delegate
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Foundation;
using Notes.iOS.Extensions;
using Notes.iOS.Services;
using Notes.Services;
using UIKit;
using UserNotifications;
using Xamarin.Essentials;
using System.Collections.Generic;
using System.Linq;
using Syncfusion.SfCalendar.XForms.iOS;
namespace Notes.iOS
{
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
IPushDemoNotificationActionService _notificationActionService;
INotificationRegistrationService _notificationRegistrationService;
IDeviceInstallationService _deviceInstallationService;
IPushDemoNotificationActionService NotificationActionService
=> _notificationActionService ??
(_notificationActionService =
ServiceContainer.Resolve<IPushDemoNotificationActionService>());
INotificationRegistrationService NotificationRegistrationService
=> _notificationRegistrationService ??
(_notificationRegistrationService =
ServiceContainer.Resolve<INotificationRegistrationService>());
IDeviceInstallationService DeviceInstallationService
=> _deviceInstallationService ??
(_deviceInstallationService =
ServiceContainer.Resolve<IDeviceInstallationService>());
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
Bootstrap.Begin(() => new DeviceInstallationService());
if (DeviceInstallationService.NotificationsSupported)
{
UNUserNotificationCenter.Current.RequestAuthorization(
UNAuthorizationOptions.Alert |
UNAuthorizationOptions.Badge |
UNAuthorizationOptions.Sound,
(approvalGranted, error) =>
{
if (approvalGranted && error == null)
RegisterForRemoteNotifications();
});
}
LoadApplication(new App());
using (var userInfo = options?.ObjectForKey(
UIApplication.LaunchOptionsRemoteNotificationKey) as NSDictionary)
ProcessNotificationActions(userInfo);
return base.FinishedLaunching(app, options);
}
void RegisterForRemoteNotifications()
{
MainThread.BeginInvokeOnMainThread(() =>
{
var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
UIUserNotificationType.Alert |
UIUserNotificationType.Badge |
UIUserNotificationType.Sound,
new NSSet());
UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
UIApplication.SharedApplication.RegisterForRemoteNotifications();
});
}
Task CompleteRegistrationAsync(NSData deviceToken)
{
DeviceInstallationService.Token = deviceToken.ToHexString();
return NotificationRegistrationService.RefreshRegistrationAsync();
}
void ProcessNotificationActions(NSDictionary userInfo)
{
if (userInfo == null)
return;
try
{
var actionValue = userInfo.ObjectForKey(new NSString("action")) as NSString;
if (!string.IsNullOrWhiteSpace(actionValue?.Description))
NotificationActionService.TriggerAction(actionValue.Description);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
=> CompleteRegistrationAsync(deviceToken).ContinueWith((task)
=> { if (task.IsFaulted) throw task.Exception; });
public override void ReceivedRemoteNotification(
UIApplication application,
NSDictionary userInfo)
=> ProcessNotificationActions(userInfo);
public override void FailedToRegisterForRemoteNotifications(
UIApplication application,
NSError error)
=> Debug.WriteLine(error.Description);
}
}
DeviceInstallationService:
using System;
using Notes.Models;
using Notes.Services;
using UIKit;
namespace Notes.iOS.Services
{
public class DeviceInstallationService : IDeviceInstallationService
{
const int SupportedVersionMajor = 13;
const int SupportedVersionMinor = 0;
public string Token { get; set; }
public bool NotificationsSupported
=> UIDevice.CurrentDevice.CheckSystemVersion(SupportedVersionMajor, SupportedVersionMinor);
public string GetDeviceId()
=> UIDevice.CurrentDevice.IdentifierForVendor.ToString();
public DeviceInstallation GetDeviceInstallation(params string[] tags)
{
if (!NotificationsSupported)
throw new Exception(GetNotificationsSupportError());
if (string.IsNullOrWhiteSpace(Token))
throw new Exception("Unable to resolve token for APNS");
var installation = new DeviceInstallation
{
InstallationId = GetDeviceId(),
Platform = "apns",
PushChannel = Token
};
installation.Tags.AddRange(tags);
return installation;
}
string GetNotificationsSupportError()
{
if (!NotificationsSupported)
return $"This app only supports notifications on iOS {SupportedVersionMajor}.{SupportedVersionMinor} and above. You are running {UIDevice.CurrentDevice.SystemVersion}.";
if (Token == null)
return $"This app can support notifications but you must enable this in your settings.";
return "An error occurred preventing the use of push notifications";
}
}
}
As you can see this is really 1:1 the example code, the only difference is that my project is called Notes.
I skipped the Firebase and Android-Part as I only need push-notifications for iOS so far and as far as I underestood these are not necessary for iOS only.
Thanks your help!
Some points to check if RegisteredForRemoteNotification not called:
Open Entitlements.plist and ensure that Enable Push Notifications is checked when viewed in the Entitlements tab. Then, ensure the APS Environment setting is set to development when viewed in the Source tab.
Make sure that you are testing the remote-notification in a real device instead of a simulator. A simulator does not support remote-notification.
Make sure that you agreed receiving notification permission.
Make sure the certification you use has enabled the push notification ability.
Refer: configuring-the-remote-notifications-environment
You can look at the message returned from the following function in your App Delegate AppDelegate.cs
public override void FailedToRegisterForRemoteNotifications(
UIApplication application,
NSError error)
For instance
no valid “aps-environment” entitlement string found for application

Exact Online Authorization

I have registered two apps(app target as 'Test') on Exact online,redirect url for one of these application is azure hosted site and other with locally hosted site.
App with locally hosted site authorizes properly and returns token successfully.
however,it fails to authorize app with azure hosted site.
OAuth2 ProtocolVersion is V20.
Can anybody help with this?
Do we need to do some settings on azure portal for Oauth2 authentication for third party software's like Exact online in this case,to get request authorized properly?
Thanks in advance.
Code sample:
region Authorize request
private static readonly ExactOnlineOAuthClient OAuthClient = new ExactOnlineOAuthClient();
private Boolean AuthorizeClient()
{
OAuthClient.Authorize(returnUri);
return (OAuthClient.Authorization != null);
}
#endregion
#region ExactOnlineOAuthClient Class
public ExactOnlineOAuthClient()
: base(CreateAuthorizationServerDescription(), ClientIdentifier(), ClientSecret())
{
ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(ClientSecret());
}
private static AuthorizationServerDescription CreateAuthorizationServerDescription()
{
var baseUri = "https://start.exactonline.nl";
var uri = new Uri(baseUri.EndsWith("/") ? baseUri : baseUri + "/");
var serverDescription = new AuthorizationServerDescription
{
AuthorizationEndpoint = new Uri(uri, "api/oauth2/auth"),
TokenEndpoint = new Uri(uri, "api/oauth2/token")
};
return serverDescription;
}
private static string ClientIdentifier()
{
return "ClientIdentifier"; //valid client id
}
private static string ClientSecret()
{
return "ClientSecret"; //valid client secret
}
private void Authorize(Uri returnUri)
{
try
{
if (Authorization == null)
{
Authorization = ProcessUserAuthorization();
if (Authorization == null)
{
// Kick off authorization request
RequestUserAuthorization(null, returnUri);
}
}
else
{
if (AccessTokenHasToBeRefreshed())
{
RefreshAuthorization(Authorization);
}
}
}
catch(Exception ex)
{
}
}
#endregion

404 /signalr/negotiate for deployed app in Azure

SignalR works on localhost but doesn't work when is deployed in Azure
Asp.net Core 1.0.0 (.Net Framework 4.6.1)
SignalR.Core 2.2.1
public static void UseSignalR2(this IApplicationBuilder app)
{
app.UseAppBuilder(appBuilder => {
appBuilder.MapSignalR(new HubConfiguration());
});
GlobalHost.HubPipeline.AddModule(new ErrorHandlingPipelineModule());
GlobalHost.HubPipeline.AddModule(new LoggingPipelineModule());
}
SignalR.js 2.2.1 with default settings
$.connection.hub.url = '/signalr';
Expected behavior
200 for url:
https://(name).azurewebsites.com/signalr/negotiate?clientProtocol=1.5&connectionData=%5B%7B%22name%22%3A%22productsimporthub%22%7D%5D&_=1472811629592
Actual behavior
/signalr/negotiate - on localhost returns 200 but for deployed app in azure returns 404
/signalr - works on both - Protocol error: Unknown transport.
/signalr/hubs - works on both - returns the SignalR js correctly
To find out the real cause of the issue you need to navigate to the negotiate url, and look for the response.
If the response tells you something about a 'CryptographicException: The data protection operation was unsuccessful...'. This is how to fix it.
1) Create a custom IDataProtectionProvider
2) Configure signalr
internal class MachineKeyProtectionProvider : IDataProtectionProvider
{
public IDataProtector Create(params string[] purposes)
{
return new MachineKeyDataProtector(purposes);
}
}
internal class MachineKeyDataProtector : IDataProtector
{
private readonly string[] _purposes;
public MachineKeyDataProtector(string[] purposes)
{
_purposes = purposes;
}
public byte[] Protect(byte[] userData)
{
//return MachineKey.Protect(userData, _purposes);
return userData;
}
public byte[] Unprotect(byte[] protectedData)
{
//return System.Web.Security.MachineKey.Unprotect(protectedData, _purposes);
return protectedData;
}
}
I use katana extension methods to bridge the IAppBuilder to IApplicationBuilder.
This allows your owin middleware to connect to asp.net core. It is important to use the RunSignalr method
app.UseAppBuilder(appBuilder =>
{
appBuilder.SetDataProtectionProvider(new MachineKeyProtectionProvider());
appBuilder.Map("/signalr", map =>
{
var hubConfiguration = new HubConfiguration
{
EnableDetailedErrors = true
};
map.RunSignalR(hubConfiguration);
});
});

ASP.NET Web Api 2, Ninject, OWIN, and IIS

I'm using Ninject for dependency injection in my ASP.NET Web Api 2 project. Everything is working perfectly locally through Visual Studio and IIS Express, but when I deploy to IIS, the dependency's are not resolved. Below is my Startup.cs
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var webApiConfiguration = new HttpConfiguration();
webApiConfiguration.EnableCors();
webApiConfiguration.SuppressDefaultHostAuthentication();
webApiConfiguration.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
webApiConfiguration.MapHttpAttributeRoutes();
app.UseNinjectMiddleware(CreateKernel).UseNinjectWebApi(webApiConfiguration);
ConfigureAuth(app);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
app.Run(async context =>
{
await context.Response.WriteAsync("Welcome to Web API");
});
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Load(new CourseModule(), new DataPullModule(), new DegreeModule(), new ResponseModule(), new RestSharpModule());
return kernel;
}
}
The error I get is when trying to access one of my controllers is below:
An error occurred when trying to create a controller of type 'DegreeController'. Make sure that the controller has a parameterless public constructor.
Here is my constructor for the DegreeController:
public DegreeController(IDegreeMapper degreeMapper, IDegreeRepository degreeRepository)
{
_degreeMapper = degreeMapper;
_degreeRepository = degreeRepository;
}
And here is the DegreeModule where I bind interfaces to classes.
public class DegreeModule : NinjectModule
{
public override void Load()
{
Bind<IDegreeController>().To<DegreeController>().InRequestScope();
Bind<IDegreeMapper>().To<DegreeMapper>().InRequestScope();
Bind<IDegreeRepository>().To<DegreeRepository>().InRequestScope();
Bind<IDegreeRatingCalculator>().To<DegreeRatingCalculator>().InRequestScope();
}
}
var kernel = CreateKernel();
app.UseNinjectMiddleware(() => kernel).UseNinjectWebApi(configuration);

Custom error pages in servicestack

How do I configure ServiceStack to serve specific error pages (404, 500, etc.) depending on the type of error being returned?
Currently, I'm using the RawHttpHandler below code to ensure that a request for a HTML file is authenticated. However, if the user specifies a non-existent file or endpoint, how can I have it return my 404.html page.
this.RawHttpHandlers.Add(httpReq =>
{
var session = httpReq.GetSession();
if(!session.IsAuthenticated) {
var isHtmlFileRequest = httpReq.PathInfo.EndsWith(".html");
if(isHtmlFileRequest && !files.Any(s => httpReq.PathInfo.ToLower().Contains(s))) {
return new RedirectHttpHandler {
AbsoluteUrl = "/Login.html"
};
}
}
return null;
});
The Error Handling wiki shows different ways to Customize Handling of Exceptions in ServiceStack, e.g you can redirect 404 errors to /404.cshtml with:
public override void Configure(Container container)
{
this.CustomHttpHandlers[HttpStatusCode.NotFound] =
new RazorHandler("/404");
}
CustomHttpHandlers can be any IServiceStackHandler which is just a HttpHandler that supports both ASP.NET and HttpListener requests. The easiest way to create one is to just inherit from IServiceStackHandler. Here's an example of a Custom Static File Handler similar to StaticFileHandler except it only writes the specified filePath instead of using the HTTP Request path:
public class CustomStaticFileHandler : HttpAsyncTaskHandler
{
string filePath;
public CustomStaticFileHandler(string filePath)
{
this.filePath = filePath;
}
public override void ProcessRequest(HttpContextBase context)
{
var httpReq = context.ToRequest(GetType().GetOperationName());
ProcessRequest(httpReq, httpReq.Response, httpReq.OperationName);
}
public override void ProcessRequest(IRequest request, IResponse response,
string operationName)
{
response.EndHttpHandlerRequest(skipClose: true, afterHeaders: r =>
{
var file = HostContext.VirtualPathProvider.GetFile(filePath);
if (file == null)
throw new HttpException(404, "Not Found");
r.SetContentLength(file.Length);
var outputStream = r.OutputStream;
using (var fs = file.OpenRead())
{
fs.CopyTo(outputStream, BufferSize);
outputStream.Flush();
}
}
}
}
This can then be registered as normal, i.e:
public override void Configure(Container container)
{
this.CustomHttpHandlers[HttpStatusCode.NotFound] =
new CustomStaticFileHandler("/404.html");
}

Resources