I am trying to integrate stripe in my asp.net application. I am using Visual Studio 17 and target .Net framework is 4.6.1
The post i followed exactly
Below is my controller code:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Stripe;
namespace DonationProgram.Controllers
{
public class DonationController : Controller
{
// GET: Donation
public ActionResult Index()
{
var stripePublishKey = ConfigurationManager.AppSettings["pk_test_Ih2IeiHk6PmK19pdh7UPijhr"];
ViewBag.StripePublishKey = stripePublishKey;
return View();
}
public ActionResult Charge(string stripeEmail, string stripeToken)
{
var customers = new StripeCustomerService();
var charges = new StripeChargeService();
var customer = customers.Create(new StripeCustomerCreateOptions
{
Email = stripeEmail,
SourceToken = stripeToken
});
var charge = charges.Create(new StripeChargeCreateOptions
{
Amount = 500,//charge in cents
Description = "Sample Charge",
Currency = "usd",
CustomerId = customer.Id
});
// further application specific code goes here
return View();
}
}
}
But there are errors in new StripeCustomerService(), new StripeChargeService() & new StripeCustomerCreateOptions saying that "the type or namespace could not be found" though i am using Stripe namespace.
It looks like that blog post is incorrect. What you should really be using is Stripe.CustomerCreateOptions or just CustomerCreateOptions. Likewise for other classes error is reporting.
For example. There is no class StripeCustomerCreateOptions in the stripe-dotnet repo, but there is just CustomerCreateOptions defined here.
Update. A bit more digging through the repo reveals that the blog post was correct at some point, but got out of date. There was a commit in August'18 that removed Stripe prefix from all the customer facing API classes.
Related
I am using Net6 web api with odata support. I am not using any apicontroller in the code and instead i am inheriting from ODataController and swagger UI is not showing the routes in the UI and event i am not able to browse those endpoints separately. Below is my samplecode
public class ValuesController : ODataController
{
[EnableQuery(PageSize = 5)]
public IQueryable<Note> Get()
{
return _context.Notes.AsQueryable();
}
}
Middleware configuration
builder.Services.AddControllers()
.AddOData(opt =>
{
opt.Conventions.Remove(opt.Conventions.OfType<MetadataRoutingConvention>()
.First());
opt.AddRouteComponents(GetEdmModel())
.Select()
.Expand()
.Count()
.Filter()
.OrderBy().SetMaxTop(100).TimeZone = TimeZoneInfo.Utc;
}).AddNewtonsoftJson(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("Notes",
new Microsoft.OpenApi.Models.OpenApiInfo { Title = "Notes API", Version = "v1", });
});
Please note I have one controller with same config and it is showing in the swagger UI, if I add new controllers inheriting from ODataController it is not working. any help appreciated.
Thanks,
Suresh
I am trying to call Google My Business API from my ASP.NET Core Web API project as shown here below:
using HighrangeModel;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using Google.Apis.Auth.OAuth2;
using Google.Apis.MyBusinessAccountManagement.v1;
using Google.Apis.Services;
using System.Net;
using Google.Apis.Auth.OAuth2.Responses;
namespace HighrangeAppliances.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class GMBController : ControllerBase
{
[Route("~/api/GetGMBAccount")]
[HttpGet]
public HttpResponseMessage GetGMBAccount()
{
var ClientId = "XXXXXXXXXXXXXXXX.apps.googleusercontent.com";
var ClientSecret = "XXXXXXXXXXXXXXXXXXX";
string[] scopes = new string[] { "https://www.googleapis.com/auth/business.manage" };
try
{
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets {
ClientId = ClientId,
ClientSecret = ClientSecret,
},
scopes,
"user",
CancellationToken.None).Result;
// TokenResponse contains the tokens, access token expiry time etc.
TokenResponse token = credential.Token;
var service = new MyBusinessAccountManagementService(new BaseClientService.Initializer() { HttpClientInitializer = credential });
var accountsListResponse = service.Accounts.List().Execute();
return new Response<string>("Listed Succesfully", JsonConvert.SerializeObject(accountsListResponse), HttpStatusCode.OK);
}
catch (Exception ex)
{
return new Response<string>(ex.Message, "", HttpStatusCode.ServiceUnavailable);
}
}
}
}
On the website https://code.google.com/apis/console I have registered my application, set up generated Client ID: and Client Secret to my app and tried to log in with Google. Unfortunately, I got this error:
Now I am using localhost to check the code and under Authorized JavaScript origins: https://localhost:44386, Authorized redirect URIs: https://localhost:44386/api/GetGMBAccount are registered.
You will need to add the redirect URI to your google cloud settings under the Client OAuth where you view your client secret, as mentioned here.
But note: If you are trying to implement server to server, this is not the right path to follow; you need to authenticate server-side not client-side, as is happening here.
Is there example code of a breeze/angular client app using ASP.Net Core Breeze server?
It looks like there are the following Nuget packages:- Breeze.AspNetCore.NetCore and Breeze.Composite.AspNetCore.EF6
It would be really helpful to have the TempHire example using this technology.
Can you point me in the right direction? re. frontend/backend code example
Any help appreciated.
This is a bit of a journey because right now there are a lot of moving parts. I have had some success in getting this to work but there are some limitations for example i cannot use .expand('entityName') on the client.
I am using .NET CORE 3.0 preview with Entity Framework Core. I have attached an image of all the dependencies i have installed. Not all of them are required but probably used in a API project.
The most important parts of the below code snippet are to setup the NewtonsoftJson settings.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
//THE BELOW LINE IS IMPORTANT OTHERWISE IT WILL CAMELCASE TO THE SERVER
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
//THE BELOW LINE PREVENTS LOOPING ENTITY REFs
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
var connection = #"Server=tcp:XXXXX.database.windows.net,1433;Initial Catalog=DBNAME;Persist Security Info=False;User ID=XXX;Password=XXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;";
//THIS IS WHERE YOU ARE GOING TO MAKE YOUR CONTEXT INJECTABLE
services.AddDbContext<YOURCONTEXTContext>(options => options.UseSqlServer(connection, x => x.UseNetTopologySuite()));
var appSettingsSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection);
// configure jwt authentication
var appSettings = appSettingsSection.Get<AppSettings>();
var key = Encoding.ASCII.GetBytes(appSettings.Token);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
Then you need to setup your breeze controller:
using Microsoft.AspNetCore.Authorization;
using System.Linq;
using HB.Data.Models;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System;
using Microsoft.AspNetCore.Mvc;
using Breeze.AspNetCore;
using HB.API.Manager;
using HB.BusinessFacade.Business;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using Breeze.Persistence;
using System.Threading.Tasks;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
namespace HB.API.Controllers
{
[BreezeQueryFilter]
[Route("api/[controller]/[action]")]
public class BreezeController : ControllerBase
{
private YOURCONTEXTContext _context;
private hbPersistenceManager PersistenceManager;
string UserID;
public BreezeController(YOURCONTEXTContext context, IHttpContextAccessor httpContextAccessor)
{
this._context = context;
PersistenceManager = new hbPersistenceManager(context);
//this.UserID = httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
}
[HttpGet]
public string Metadata()
{
return PersistenceManager.Metadata();
}
}
And then just a little helper that i use for the PersistenceManager
using HB.Data.Models;
using Breeze.Persistence.EFCore;
namespace HB.API.Manager
{
public class hbPersistenceManager : EFPersistenceManager<YOURCONTEXTContext>
{
public hbPersistenceManager(YOURCONTEXTContext dbContext) : base(dbContext) { }
}
}
Please see this example: https://github.com/Breeze/northwind-demo
It is a full working example with a .NET Core 2.2 backend and Angular 8 front end, and includes TypeScript class generation so that the client-side TypeScript model matches the server-side C# model and database.
The example repo includes steps to create the entire app from scratch.
I have this ASP.NET MVC 5 project which I'm converting over to AngularJS with MS Web Api.
Now in the old project I have these c# controllers of type Controller, however in my new project I've created some new Web Api controllers of type ApiController.
Now I'd like to reuse the old controller code in my new project. Herein lies my confusion.
As I attempt to port the old controller code over to my Web Api controller, I'm getting some front-end $http request errors.
Here's a function from my Angular dataService factory which makes an http req down to 'api/Whatif/SummaryPortfolios':
function getCurrPortfoliosLIst() {
var deferred = $q.defer();
var url = 'api/Whatif/SummaryPortfolios';
var req={
method: 'POST',
url: url,
headers: {
'Content-Type': 'application/json',
},
data:{}
};
$http(req).then(function (resp){
deferred.resolve(resp.data);
}, function(err){
console.log('Error from dataService: ' + resp);
});
}
But the $http error section is returning this exception:
data: Object
ExceptionMessage: "Multiple actions were found that match the request:
↵SummaryPortfolios on type MarginWorkbenchNG.Controllers.WhatifController
↵Post on type MarginWorkbenchNG.Controllers.WhatifController"
ExceptionType: "System.InvalidOperationException"
Message: "An error has occurred."
StackTrace: " at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)
↵ at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)
↵ at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
↵ at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
Here's the c# API controller I'm calling down to, but I need to figure out how to create methods other than straight Get() and Post() methods:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using Microsoft.AspNet.Identity;
using NLog;
using Microsoft.AspNet.Identity.Owin;
using MarginWorkbenchNG.Models;
using Rz.DAL;
using Rz.DAL.Integration;
using Rz.DAL.Models;
using Rz.DAL.Models.Rz;
namespace MarginWorkbenchNG.Controllers
{
public class WhatifController : ApiController
{
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
[HttpPost]
public List<WhatifSummaryViewModel> SummaryPortfolios(string filterValue = "", int? whatIfBatchNumber = null, bool includeBaseline = true)
{
// Get portfolios from Rz
IEnumerable<Portfolio> portfolios = GetPortfolios(filterValue, whatIfBatchNumber, includeBaseline)
.Where(x => x.PortfolioKeys.Any(k => k.Type == Settings.Whatif.SidebarPortfolioKey && k.DisplayValue == filterValue));
// View Model
List<WhatifSummaryViewModel> model = new List<WhatifSummaryViewModel> { };
/// additional code here...
return model;
}
}
}
The old controller (from the MVC5 project) looks slightly different of course because the _Summary method is of type ActionResult and returns a Partial:
public class WhatifController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult _Summary(string filterValue = "", int? whatIfBatchNumber = null, bool includeBaseline = true)
{
// Get portfolios from Razor
IEnumerable<Portfolio> portfolios = GetPortfolios(filterValue, whatIfBatchNumber, includeBaseline)
.Where(x => x.PortfolioKeys.Any(k => k.Type == Settings.Whatif.SidebarPortfolioKey && k.DisplayValue == filterValue));
// View Model
List<WhatifSummaryViewModel> model = new List<WhatifSummaryViewModel> { };
// additional code removed for brevity...
return PartialView(model.OrderBy(x => x.Title).ThenBy(x => x.SubTitle));
}
My RouteConfig.cs :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MarginWorkbenchNG
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
The old project also uses Html forms to pull the URL, for example:
<form id="whatif-summary-form" action="#Url.Action("_Summary", "WhatIf")" method="POST"></form>
and then pulls the action attrib to get the URL when building out the ajax request in JavaScript (non-Angular) :
url: form.prop("action")
Is this your entire ApiController? The error message you are receiving is because your ApiController has several methods that are of the same type and it can't tell which one to route to. To test this: comment out all of your controller's methods except the one you are calling. You shouldn't receive that error anymore.
This is an easy fix, just tell web api how to map your route. Add the attribute '[Route("yourroute')]' to your method and it should work.
public class WhatifController : ApiController
{
[HttpPost, Route("Your Route Goes here 'SummaryPortfolios'")]
public IHttpActionResult SummaryPortfolios(string filterValue = "", int? whatIfBatchNumber = null, bool includeBaseline = true)
{
// Get portfolios from Rz
IEnumerable<Portfolio> portfolios = GetPortfolios(filterValue, whatIfBatchNumber, includeBaseline)
.Where(x => x.PortfolioKeys.Any(k => k.Type == Settings.Whatif.SidebarPortfolioKey && k.DisplayValue == filterValue));
// View Model
List<WhatifSummaryViewModel> model = new List<WhatifSummaryViewModel> { };
/// additional code here...
return Ok(model);
}
}
I'm new to the MVC framework and wondering how to pass the RSS data from the controller to a view. I know there is a need to convert to an IEnumerable list of some sort. I have seen some examples of creating an anonymous type but can not figure out how to convert an RSS feed to a generic list and pass it to the view.
I don't want it to be strongly typed either as there will be multiple calls to various RSS feeds.
Any suggestions.
I've been playing around with a way of doing WebParts in MVC which are basically UserControls wrapped in a webPart container. One of my test UserControls is an Rss Feed control. I use the RenderAction HtmlHelper extension in the Futures dll to display it so a controller action is called. I use the SyndicationFeed class to do most of the work
using (XmlReader reader = XmlReader.Create(feed))
{
SyndicationFeed rssData = SyndicationFeed.Load(reader);
return View(rssData);
}
Below is the controller and UserControl code:
The Controller code is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Xml;
using System.ServiceModel.Syndication;
using System.Security;
using System.IO;
namespace MvcWidgets.Controllers
{
public class RssWidgetController : Controller
{
public ActionResult Index(string feed)
{
string errorString = "";
try
{
if (String.IsNullOrEmpty(feed))
{
throw new ArgumentNullException("feed");
}
**using (XmlReader reader = XmlReader.Create(feed))
{
SyndicationFeed rssData = SyndicationFeed.Load(reader);
return View(rssData);
}**
}
catch (ArgumentNullException)
{
errorString = "No url for Rss feed specified.";
}
catch (SecurityException)
{
errorString = "You do not have permission to access the specified Rss feed.";
}
catch (FileNotFoundException)
{
errorString = "The Rss feed was not found.";
}
catch (UriFormatException)
{
errorString = "The Rss feed specified was not a valid URI.";
}
catch (Exception)
{
errorString = "An error occured accessing the RSS feed.";
}
var errorResult = new ContentResult();
errorResult.Content = errorString;
return errorResult;
}
}
}
The UserControl
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="Index.ascx.cs" Inherits="MvcWidgets.Views.RssWidget.Index" %>
<div class="RssFeedTitle"><%= Html.Encode(ViewData.Model.Title.Text) %> <%= Html.Encode(ViewData.Model.LastUpdatedTime.ToString("MMM dd, yyyy hh:mm:ss") )%></div>
<div class='RssContent'>
<% foreach (var item in ViewData.Model.Items)
{
string url = item.Links[0].Uri.OriginalString;
%>
<p><a href='<%= url %>'><b> <%= item.Title.Text%></b></a>
<% if (item.Summary != null)
{%>
<br/> <%= item.Summary.Text %>
<% }
} %> </p>
</div>
with the code behind modified to have a typed Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ServiceModel.Syndication;
namespace MvcWidgets.Views.RssWidget
{
public partial class Index : System.Web.Mvc.ViewUserControl<SyndicationFeed>
{
}
}
#Matthew - perfect solution - as an alternative to code behind which tends to break the MVC concept, you can use:
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SyndicationFeed>" %>
<%# Import Namespace="System.ServiceModel.Syndication" %>
Using MVC you don't even need to create a view, you can directly return XML to the feed reader using the SyndicationFeed Class.
(Edit) .NET ServiceModel.Syndication - Changing Encoding on RSS Feed this is a better way. (snip from this link instead.)
http://msdn.microsoft.com/en-us/library/system.servicemodel.syndication.syndicationfeed.aspx
public ActionResult RSS(string id)
{
return return File(MyModel.CreateFeed(id), "application/rss+xml; charset=utf-8");
}
In MyModel
CreateFeed(string id)
{
SyndicationFeed feed = new SyndicationFeed( ... as in the MS link above)
.... (as in the MS link)
//(from the SO Link)
var settings = new XmlWriterSettings
{
Encoding = Encoding.UTF8,
NewLineHandling = NewLineHandling.Entitize,
NewLineOnAttributes = true,
Indent = true
};
using (var stream = new MemoryStream())
using (var writer = XmlWriter.Create(stream, settings))
{
feed.SaveAsRss20(writer);
writer.Flush();
return stream.ToArray();
}
}
A rss is a xml file with special format. You may design a dataset with that generic format and read the rss(xml) with ReadXml method and the uri as the path to the file. Then you have got a dataset you can consume from another clases.