Base solution for your next web application

Activities of "justinp"

Oh, and I should mention that I have a method called GetConnections that works fine from that service.

I think you are onto something there...

I created a simple method inside the same ConnectionsApplciationService that accepts no arguments and returns a string, and still get an error when calling from my Angular client!

public string TestConnectionWithoutPassingConnectionString()
        {
            try
            {              
                return "SUCCESS!";
            }
            catch (Exception ex) { return "ERROR: " + ex.Message; }
        }

So the issue must be with the ConnectionsApplicationService. However, I have other ApplicationServices that don't have this issue. Here's some more info on the implementation (some I provided earlier but put here again so it is easy to reference).

ConnectionsApplicationService:

public class ConnectionsAppService : ApplicationService, IConnectionsAppService

IConnectionsApplicationService:

public interface IConnectionsAppService : IApplicationService

Again, I have other several other services that inherit from ApplicationService in the same way.

I plan on using Recurly for payment and am in the process of implementing. Can you guys provide an overview of the subscription implementation and maybe I can use the same pattern and make available to the community.

What I was planning on implementing isn't just a single subscription option, but also a licensing model. In other words, there is a way to charge based on the number of active accounts for that month. For example, $100/mo + $15/user/mo.

A future feature in consideration for my project is the ability to charge per month or per year, offering a discount per annual payment of course.

Thanks.

I don't understand why I need a special configuration either. However I am getting the error, so something must be done.

Yes, all other app services are accessible from angular UI without CORS.

No, I am not using another client app. This is a simple form built into the Angular front end.

Here's how you reproduce using the Angular + Core solution:

  1. Create an ApplicationService with a method that calls an external/public web service and returns a simple string of either "success" or "error" using a try/catch block. I do this so that I receive a string back no matter what happens within the code.
  2. Build/Run the app and run nswag/refresh.bat to update the service proxy class in the Angular solution.
  3. Create a simple form in the Angular solution with a button that calls the service.

If you set a break point in your web-service call, you will notice that it returns the result without issue. But when received by the browser, you get the error I posted.

Thank you.

As I mentioned in my previous post, I am passing the connection string from the Angular App to the .NET Core API, which tests the connection and passes the result back to the Angular App.

Let me know what else I need to do to enable CORS.

Before I step away from this issue, I wanted to provide the header that is returned. As the error indicates, there is "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 500."

Here is the header with the error:

POST /api/services/app/Connections/TestConnection?connectionString=http%3A%2F%2Fspark.furore.com%2Ffhir& HTTP/1.1
Host: localhost:22742
Connection: keep-alive
Content-Length: 0
**Origin: http://localhost:4200**
Abp.TenantId: 1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjIiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYWRtaW4iLCJBc3BOZXQuSWRlbnRpdHkuU2VjdXJpdHlTdGFtcCI6IjI2YzRhNzE3LTEzYzYtZWY3Ni1kMjQzLTM5ZGYzZGI3NDY5NSIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvcm9sZSI6IkFkbWluIiwiaHR0cDovL3d3dy5hc3BuZXRib2lsZXJwbGF0ZS5jb20vaWRlbnRpdHkvY2xhaW1zL3RlbmFudElkIjoiMSIsInN1YiI6IjIiLCJqdGkiOiIxZDY0ZTM1YS1kMmUzLTRlNTItODQ4NC1lYzU3Yzk0MjM2YTIiLCJpYXQiOjE0OTgzNjg3NDksIm5iZiI6MTQ5ODM2ODc0OSwiZXhwIjoxNDk4NDU1MTQ5LCJpc3MiOiJhcG9sbG8iLCJhdWQiOiJhcG9sbG8ifQ.BobvLtaes8XAFpFQU5FGKr9QBCALF1Mx2HSj7GYfnVo
Content-Type: application/json; charset=UTF-8
Accept-Language: en
Accept: application/json; charset=UTF-8
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Referer: http://localhost:4200/app/admin/connections
Accept-Encoding: gzip, deflate, br

I am not a CORS expert, but the default ABP policy defined explicity defines <a class="postlink" href="http://localhost:4200">http://localhost:4200</a>, and trying to allow all origins doesn't give the proper header in response.

Other thing's I've tried, but still it is not working.

  1. Adding "http:/" or just "" to the appsettings.json file
"CorsOrigins": "http://localhost:4200,http://localhost:49152,http://*,*"
  1. Adding an additional policy within Startup.cs and then adding that policy to the web service. Note, this requires adding Microsoft.AspNetCore.Cors NuGet package to the Application project. I was basically following the Microsoft documentation here (<a class="postlink" href="https://docs.microsoft.com/en-us/aspnet/core/security/cors">https://docs.microsoft.com/en-us/aspnet ... urity/cors</a>). Policy definition:
//Configure CORS for angular2 UI
            services.AddCors(options =>
            {
                options.AddPolicy(DefaultCorsPolicyName, builder =>
                {
                    //App:CorsOrigins in appsettings.json can contain more than one address with splitted by comma.
                    builder
                        .WithOrigins(_appConfiguration["App:CorsOrigins"].Split(",", StringSplitOptions.RemoveEmptyEntries).Select(o => o.RemovePostFix("/")).ToArray())
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                });
                options.AddPolicy("TestConnectionPolicy", builder => 
                {
                    builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin();
                });
            });

And here's the policy declaration on the service.

using Microsoft.AspNetCore.Cors;

namespace Company.Project.Connections
{
    [EnableCors("TestConnectionPolicy")]
    public class ConnectionsAppService : ApplicationService, IConnectionsAppService
    {

What really throws me is the error specifies <a class="postlink" href="http://localhost:4200">http://localhost:4200</a>, which **IS**in the appsettings.json file.

I found a way to get this stop throwing the jTable error dialog, but I still have the issue where the modal style is taking up the entire width. It's not an elegant solution, but this might be helpful or start a discussion on the correct way to use jTable within ABPZ Core + Angular.

updateAction: (postData) => {
                    var patientServiceProxy = $.proxy(this._patientServiceProxy.updateCensusMonth, this._patientServiceProxy);
                    var pairs = new String(postData).split('&');
                    var result = {};
                    pairs.forEach(function (pair) {
                        var newPair = pair.split('=');
                        result[newPair[0]] = decodeURIComponent(newPair[1] || '');
                    });
                    var cm = new CensusMonthDto(JSON.parse(JSON.stringify(result)));
                    return $.Deferred((function ($dfd) {
                        var s = patientServiceProxy(cm).subscribe(
                            (result) => { },
                            (result) => {  $dfd.reject();  },
                            () => {
                                var result = JSON.parse('{ "Result" : "OK" }');
                                $dfd.resolve(result);
                            }
                        );
                    }));
                }

Notes on how this works:

  1. I used $.proxy for my service proxy method call because you will lose context inside $.Deferred.

  2. I parsed the 'postData' which is in querystring format and built a JSON formated string. I then strigify and parse the string to create my censusMonthDto object to pass to the service proxy.

  3. I included ALL required fields for the Dto into the form and hacked the input option to show a span, and hide an input. Here is an example of what I had to do because I needed to post Year, but not allow it to be modified:

year: {
                    title: 'Year',
                    input: function (data) {
                        if (data.value) {
                            return '<span>' + data.value + '</span><input type="text" name="year" style="visibility: hidden;" value="' + data.value + '" />';
                        } else {
                            return '<input type="text" name="year" value="" />';
                        }
                    }
                },

jTable has all kinds of bugs where it will not post the field. For example if you disable the input, it will not post. There doesn't seem to be a way to have the field in the table, not have the field on the form, but to post the field with the rest of the form data. The 'key' field actually does this, but I couldn't replicate it with the options available.

  1. I have to "fake" the JSON result inside my service proxy call to satisfy jTable. Maybe the guys could make and aTable for Angular. :lol:

I'm still chipping away. Here's what I know:

  1. jTable (made by the same people as ABP) doesn't seem to have their own style for modals. ABP does not implement a jQueryUI theme for the jTable modals. Something within the way the styles are applied in ABP makes the jTable modal take up the entire width of the page. I've tried to override it, but can't seem to get control of the modal's style. This should be easy to reproduce. I copied the dashboard, replaced all the content with a single portlet div and jTable, then implemented the jTable. What is the correct way to implement jTable modals in ABP?

  2. The jTable error is because jTable wants a specific result returned. From the jTable site:

A function (that is set as action) can either return the data jTable needs or can return a promise using jQuery.Deffered object (as implemented in this demo) to return data later. Data must be formatted as described in documentations. If your server returns data formatted different than jTable expects, you must convert to jTable format in your function. Unfortunately, ABP uses the service-proxies, which has functions that return Observables. Observables and Deferred are similar in concept, but not the same thing. How can I return a what jTable wants?

this._patientServiceProxy.updateCensusMonth(cm).subscribe(
                        (result) => { },
                        (result) => { console.log("ERROR! " + result); },
                        () => {
                            //here I need to return a jQuery deferred resolution
                        }
                    );

I received a notice that the email got kicked back by your provider. I sent the files as a .zip.

mx.google.com rejected your message to the following email addresses:
AspNet Zero Info ([email protected])
Your message wasn't delivered because the recipient's email provider rejected it.
mx.google.com gave this error:
This message was blocked because its content presents a potential security issue. Please visit https://support.google.com/mail/?p=BlockedMessage to review our message content and attachment content guidelines. p21si876118pgc.277 - gsmtp
Showing 11 to 20 of 59 entries