I have created a plugin for brain-tree payment integration that gets load on run time therefore i have generated the client token on the server side c# class and i am trying to use that in my angular controller but unable to do so.
Is there any way that i can get my session variable or some thing like that in my angular controller from c# class? so that i will be able to create drop-in UI in angular ready function.
I want to acheive something like this:
angular.element(document).ready(function () {
var clientToken = "From_Server_Side";
braintree.setup(clientToken , 'dropin', {
container: 'dropin-container',
paypal: {
singleUse: true,
amount: 10.00,
currency: 'GBP'
}
});
});
You have to make a JsonResult like this in your controller
[HttpGet]
public JsonResult client_token()
{
var gateway = config.GetGateway();
var clientToken = gateway.ClientToken.Generate();
return Json(clientToken, JsonRequestBehavior.AllowGet);
}
and then in your angularjs you have to do
$scope.get_token = function () {
$http({
method: 'GET',
url: '/home/client_token'
}).then(function (data) {
$scope.client_token_string = data.data;
})
}
$scope.get_token();
I put home hypothetically assuming that your doing it in home controller
Related
When a user clicks a drop down item I want to refresh a view component depending on what the user chose in the drop down. I have tried different ways to get the component to render but each one has resulted in a 500 error. I know that my ajax and scripts calls are making it to my controller because of debug and once the controller returns, I get the 500 error
Here is the cshtml snippet of view comp:
<div id="component" class="panel-body">
#await Component.InvokeAsync("tk", new Timecard() { TimeCardType = Model.Flsa })
</div>
Here is the Controller code I am trying to call:
[HttpGet]
public IActionResult RefreshView(string flsa)
{
if (flsa == "N")
return NonExempt(flsa);
else
return Exempt(flsa);
}
public IActionResult NonExempt(string flsa)
{
return ViewComponent("_NonExempt", new Timecard() { TimeCardType = flsa });
}
public IActionResult Exempt(string flsa)
{
return ViewComponent("Exempt", new Timecard() { TimeCardType = flsa });
}
And here are a couple of attempts in js/ajax to try and refresh it:
$.ajax({
url: 'RefreshView',
data: { flsa: 'N' },
method: "GET"
}).done(function (res) {
$('#component').html(res);
});
and:
$(function () {
$('#component').load('RefreshView', {
flsa: result.flsa
});
});
And here is the error:
jquery.js:9600 GET http://localhost:61440/TimeKeeper/RefreshView?flsa=N 500 (Internal Server Error)
Like I said, both of the above js snippets hit my controller fine.
screenshot oferror
enter image description here
I am trying to use Braintree's payment DropinUI, and configuring it requires sending a generated token
to a javascript function in my page. I have the following markup in my Razor Page:
<div id="dropin-container"></div>
<button id="submit-button">Request payment method</button>
<script>
function configureBraintreeClient(clientToken) {
var button = document.querySelector('#submit-button');
braintree.dropin.create({
authorization: clientToken,
container: '#dropin-container'
}, function (createErr, instance) {
button.addEventListener('click', function () {
instance.requestPaymentMethod(function (requestPaymentMethodErr, payload) {
// Submit payload.nonce to your server
});
});
});
}
</script>
The div #dropin-container is populated by the result of the function configureBraintreeClient. So, I need to pass in a clientToken when the page loads.
My page model to generate a client token:
public class IndexModel : PageModel
{
private readonly IJSRuntime _jsRuntime;
public IndexModel(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
public IActionResult OnGet()
{
// Create gateway
var gateway = new BraintreeGateway
{
Environment = Environment.SANDBOX,
MerchantId = "xxxxxxx",
PublicKey = "xxxxxxx",
PrivateKey = "xxxxxxx"
};
var clientToken = gateway.ClientToken.Generate();
JSRuntimeExtensions.InvokeVoidAsync(_jsRuntime, "configureBraintreeClient", clientToken);
// Not sure if this is needed, doesn't work with return type of
// void and this line removed either.
Page();
}
}
This does not work. The div is never populated.
I can insert a client token directly into the markup and it runs perfectly, so it has something to do with passing the client token
to the page from the page model. Should I not be using the JSRuntime extension?
I've tried setting the client token as a model property and inserting it in the function with razor syntax like authorization: #Model.ClientToken
but it doesn't work.
I've tried to dig around to understand the page life cycle better but nothing I have found has helped me figure out this issue.
I see no errors in the developer console of my browser or in Visual Studio, but I don't know a lot about debugging javascript in ASP .NET Core.
What's the proper way to pass a parameter into a javascript function that updates a div like this?
For we do not have merchant ID,Public key andPrivate key,be sure that you have generated the correct token,then you could try this:
1.IndexModel():
private readonly IJSRuntime _jsRuntime;
public IndexModel(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
[BindProperty]
public string clientToken { get; set; }
public void OnGet()
{
// Create gateway
var gateway = new BraintreeGateway
{
Environment = Braintree.Environment.SANDBOX,
MerchantId = "xxxxxxx",
PublicKey = "xxxxxxx",
PrivateKey = "xxxxxxx"
};
clientToken = gateway.ClientToken.Generate();
JSRuntimeExtensions.InvokeVoidAsync(_jsRuntime, "configureBraintreeClient", clientToken);
}
2.Razor Page(no need to use function):
<div id="dropin-container"></div>
<button id="submit-button">Request payment method</button>
<script src="https://js.braintreegateway.com/web/dropin/1.20.4/js/dropin.min.js">
</script>
<script>
var button = document.querySelector('#submit-button');
braintree.dropin.create({
authorization: '#Model.clientToken',
container: '#dropin-container'
}, function (createErr, instance) {
button.addEventListener('click', function () {
instance.requestPaymentMethod(function (requestPaymentMethodErr, payload) {
// Submit payload.nonce to your server
});
});
});
</script>
3.Test(You could see that the token has filled into the js):
Reference:
https://developers.braintreepayments.com/start/hello-client/javascript/v3
I can insert a client token directly into the markup and it runs perfectly, so it has something to do with passing the client token to the page from the page model. Should I not be using the JSRuntime extension?
For this,if you want to use client token,I suggest that you could refer to:
https://developers.braintreepayments.com/start/tutorial-drop-in-node
For authorization,you could also use tokenization key.
The issue here is, that i don't know how to pass some scope.data to expressjs when using ngResource, so then it can be used with express route to insert something to DB.
ExpressJS REST
router.route('/Data')
.get(function(req,res){
var username = req.username;
var collection = db.collection('users');
collection.find({username:username}).toArray(function (err, doc){
res.send(doc[0].pets);
});
})
.post(function(req,res){
!!//I would like to use some data from angular here//!!
var name = req.body.name;
var surname = req.bodysurname;
collection.update({username: username}, {
$push: {
"details": {
name: name,
surname: surname
}
}
}, function (err, result) {
if (err) throw err;
});
});
Angular Factory
(function() {
'use strict';
angular
.module('App')
.factory('Factory', function ($resource) {
return $resource("/Data",{},
{ get:{ method:"GET",
cache:true,
isArray:true},
save:{ method:"POST",
cache:true,
isArray:false
}});
});
})();
Controller.js
This one works fine i use this function with ng-click()
$scope.load = function(){
Factory.get(function (data){
$scope.data = data;
});
};
With this one i have problem i have ng-models name and surname in view and i would like to send them to server so it can be used in REST route as req.body.name and req.body.surname.
$scope.AddData = function(){
Factory.save()
});
};
I think that data should be passed here in this function AddData, however i haven't succeeded yet.
So i tried as Jesus said but without results?
$scope.AddData = function(){
Factory.save($scope.name) //I tried ({name:$scope.name}) too
});
};
After advices from Jesús Quintana I checked the details of method POST and it occurred that everything was all right on angular side i was missing extension of body parser on server Express side
app.use(bodyParser.json())
So now it looks like this
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
NgResource works like a class with private and public methods:
For example Factory.save() is a public method and you must pass the data to be stored in the server, for example:
$scope.AddData = function(factoryData){
Factory.save(factoryData);
});
};
But also have a private method and the above example is the same to this:
$scope.AddData = function(factoryData){
var factory = new Factory(factoryData);
factory.$save(); // Is the same method but is private because factory is a instance of the factory
});
};
Both example are valid methods but must be used of differents ways.
EDIT
I create this little plunkr to see the network request: http://plnkr.co/edit/1bdblyrsW0jr7rXIAVNn?p=
I am working on a POC using a very old asp.net application that runs winforms, and adding a REST API to it. I have so far been successful up until this one endpoint, and it is not giving me my data back in my controller.
I have more experience in an MVC framework and web API then the current implementation I am working in. What I need help with is how I can get my data sent back to the server.
Here is my code:
this is the equivalent of my global asax file
class Startup
{
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });
appBuilder.UseCors(CorsOptions.AllowAll);
appBuilder.UseWebApi(config);
}
}
Javascript
var setPatient = function () {
$.ajax({
url: "http://localhost:9000/api/context/readPtnt?contextData=&type=context",
type: "POST",
dataType: "json",
contentType:"application/json; charset=utf-8",
data: {
jsonData: JSON.stringify({
firstName: $('#fName').val(),
lastName: $('#lName').val(),
ID: $('#ID').val(),
DOB: $('#DOB').val(),
SSN: $('#SSN').val(),
MRN: $('#MRN').val()
})
}
})
.done(successPatientSet)
.fail(errorFn)
.always(function (data, textStatus, jqXHR) {
});
}
//click
$("#btnSetPatientData").on("click", setPatient);
and my controller code:
[HttpPost]
[Route("/api/context/readPtnt")]
public string ReadPtnt(string contextData, string type)
{
try
{
var patientInfo = PatientContext.Create(contextData);
I can successfully hit the back end, but I get nothing in the contextData variable, when I try to change that variable name I get 404's. I have tried all sorts of variations from different iterations of my JQuery, as well as pure javascript Ajax calls. The REST middleware that we are using is OWIN. I am stumped, any input would be helpful. Thanks.
You need enable CORS support
To enable CORS support, add the Microsoft.AspNet.WebApi.Cors NuGet package to your project.
Add this code to your configuration:
public static void Register(HttpConfiguration config)
{
// New code
config.EnableCors();
}
To enable cross-origin requests, add the [EnableCors] attribute to your Web API controller or controller method:
[EnableCors(origins: "http://example.com", headers: "*", methods: "*")]
public class TestController : ApiController
{
// Controller methods not shown...
}
Enabling Globally
The method described above can also be used to enable CORS across the API without annotating each controller:
public static void Register(HttpConfiguration config)
{
var corsAttr = new EnableCorsAttribute("http://example.com", "*", "*");
config.EnableCors(corsAttr);
}
For more information, see the official Web API documentation.
I have a post request I am doing like so:
var addProject = function (project, id) {
return $.ajax(projectUrl, {
type: "POST",
data: { project: project, id: id }
});
};
This is all fine, and it send up my project object (in JSON) with no problem. What i want to do is this request but also add in a key (that does not belong in the project object) that I can pass to the server controller. Any idea if I can do this, or what is a good way to do this. I really don't want to have to go back and change my object models to account for a key that I will only need every once in awhile.
This is an ASP.NET MVC4 project, and it is going back to a web api controller if that matters.
EDIT: here is my server side stuff
public HttpResponseMessage PostNew(Project project, int id)
{
//TODO grab the client to add the project to
Uow.Projects.Add(project);
Uow.Commit();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, project);
//response.Headers.Location = new Uri(Url.Link("ApiControllerAction", new { id = client.ID }));
return response;
}
Maybe I am not being clear enough. I want to pass in the project object, and then just an int variable. Passing project alone works, but if I try to pass the int it gives me a 400 error
var addProject = function (project) {
return
$.ajax(projectUrl, {
type: "POST",
data: {data1 : 'Object',data2: 'variable'}
});
};
You have just to send 2 data params., object and var..
Easiest way to pass a complex object is to JSON-encode it:
var addProject = function (project) {
return $.ajax(projectUrl, {
type: "POST",
contentType: 'application/json',
data: JSON.stringify(project)
});
};
To decode this on the server side, you will need a JSON decoder of some kind. I'm sure C# has some available.