Unable to connect Azure Function App with Database (using .net core 2.1) - asp.net-core

Please note (Environment):
Function App: Version 2,
Target Framework: .Net Core 2.1
I am developing a Function App, that will work like Web Api. This Function App will return the data from database tables, also it'll manipulate files in Azure storage(Blob). But I am stuck as I am unable to create ConnectionString from local.settings.json file. Ideally the connection string should be created by default as I followed some tutorials & no where mentioned any extra steps to create default connectionstring value, just need to create it in local.settings.json file.
following is my local.settings.json file content:-
{
"ConnectionStrings": {
"mycs": "data source=servername;initial catalog=dbname;user id=XXXX;password=XXXX;MultipleActiveResultSets=True;"
},
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"mycs": "data source=servername;initial catalog=dbname;user id=XXXX;password=XXXX;MultipleActiveResultSets=True;"
}
}
following is my HttpTrigger file:
namespace my_api
{
public class myDataContext : DbContext
{
public myDataContext() : base(GetConnectionString()) { }
private static string GetConnectionString()
{
const string providerName = "System.Data.SqlClient";
const string metadata = #"res://*/MYDB.csdl|res://*/MYDB.ssdl|res://*/MYDB.msl";
try
{
string connectString = ConfigurationManager.ConnectionStrings["mycs"].ToString();
// Initialize the connection string builder for the
// underlying provider.
SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder(connectString);
// Set the properties for the data source.
//sqlBuilder.IntegratedSecurity = true;
sqlBuilder.MultipleActiveResultSets = true;
// Build the SqlConnection connection string.
string providerString = sqlBuilder.ToString();
// Initialize the EntityConnectionStringBuilder.
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
//Set the provider name.
entityBuilder.Provider = providerName;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString;
// Set the Metadata location.
entityBuilder.Metadata = metadata;
return entityBuilder.ConnectionString;
}
catch { }
var connectionstring = Environment.GetEnvironmentVariable("mycs");
return connectionstring;
}
public DbSet<flowerset> flowersets
{
get;
set;
}
}
}
Following is the code for :
namespace my_api
{
public static class helpService
{
[FunctionName("helpService_get")]
public static async Task> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
ILogger log, ExecutionContext context)
{
log.LogInformation("C# HTTP trigger function processed a request helpService_get).");
try {
int page = 0;
int pageSize = 20;
myDataContext entity = new myDataContext();
if (page == 0 && pageSize == 0)
{
return entity.helpsets.ToList();
}
if (pageSize <= 0) { pageSize = 20; }
entity.helpsets.OrderByDescending(x => x.id).Skip((page - 1) * pageSize).Take(pageSize).ToList();
}
catch (Exception exx) {
log.LogInformation("Exception changed (helpService_get): "+exx.Message);
}
return null;
}
}//End of Class
}//End of Namespace
I am getting following error on line entity.helpsets.OrderByDescending(x => x.id).Skip((page - 1) * pageSize).Take(pageSize).ToList();:
Unable to determine the provider name for provider factory of type 'System.Data.SqlClient.SqlClientFactory'. Make sure that the ADO.NET provider is installed or registered in the application config.

According to my test, we can use System.Data.SqlClient to connect Azure SQL in Azure function V2.0. For example
Create an Azure Function with Visual Studio 2019
Install System.Data.SqlClient package(the version I sue is 4.5.1)
Develop the function
local.settings.json file content
"ConnectionStrings": {
"mycs": "Data Source="";Initial Catalog=DotNetAppSqlDb20190826105048_db;User Id="";Password="" "
},
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
Code
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
try
{
var connectionstring = System.Environment.GetEnvironmentVariable($"ConnectionStrings:mycs"); ;
using (SqlConnection connection = new SqlConnection(connectionstring))
{
connection.Open();
log.LogInformation(" sql login success");
StringBuilder sb = new StringBuilder();
sb.Append("select * from dbo.Todoes");
String sql = sb.ToString();
using (SqlCommand command = new SqlCommand(sql, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
log.LogInformation("{0} {1}", reader.GetInt32(0), reader.GetString(1));
}
}
}
connection.Close();
}
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
For more details, please refer to the document

Related

Are there advantages of using .NET Core's middleware "Health checks" over just a ping in a controller's route?

I'm reading a "Asp.net Core 3 and Angular 9" book and there is an example usage of .NET Core Health check.
It's also described on Microsoft website: https://learn.microsoft.com/en-US/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-3.0
I can't find a reason to actually use it over just creating a route in some controller which will ping external addresses.
Code in a book goes like this:
Add this in Configure (Startup.cs) method:
app.UseHealthChecks("/hc", new CustomHealthCheckOptions());
ConfigureServices method:
services.AddHealthChecks()
.AddCheck("ICMP_01", new ICMPHealthCheck("www.ryadel.com", 100))
.AddCheck("ICMP_02", new ICMPHealthCheck("www.google.com", 100))
.AddCheck("ICMP_03", new ICMPHealthCheck("www.does-notexist.com", 100));
Create ICMPHealthCheck.cs file:
using Microsoft.Extensions.Diagnostics.HealthChecks;
using System;
using System.Net.NetworkInformation;
using System.Threading;
using System.Threading.Tasks;
namespace HealthCheck
{
public class ICMPHealthCheck : IHealthCheck
{
private string Host { get; set; }
private int Timeout { get; set; }
public ICMPHealthCheck(string host, int timeout)
{
Host = host;
Timeout = timeout;
}
public async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
try
{
using (var ping = new Ping())
{
var reply = await ping.SendPingAsync(Host);
switch (reply.Status)
{
case IPStatus.Success:
var msg = String.Format(
"IMCP to {0} took {1} ms.",
Host,
reply.RoundtripTime);
return (reply.RoundtripTime > Timeout)
? HealthCheckResult.Degraded(msg)
: HealthCheckResult.Healthy(msg);
default:
var err = String.Format(
"IMCP to {0} failed: {1}",
Host,
reply.Status);
return HealthCheckResult.Unhealthy(err);
}
}
}
catch (Exception e)
{
var err = String.Format(
"IMCP to {0} failed: {1}",
Host,
e.Message);
return HealthCheckResult.Unhealthy(err);
}
}
}
}
Create CustomHealthCheckOptions.cs file:
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Net.Mime;
using System.Text.Json;
namespace HealthCheck
{
public class CustomHealthCheckOptions : HealthCheckOptions
{
public CustomHealthCheckOptions() : base()
{
var jsonSerializerOptions = new JsonSerializerOptions()
{
WriteIndented = true
};
ResponseWriter = async (c, r) =>
{
c.Response.ContentType =
MediaTypeNames.Application.Json;
c.Response.StatusCode = StatusCodes.Status200OK;
var result = JsonSerializer.Serialize(new
{
checks = r.Entries.Select(e => new
{
name = e.Key,
responseTime = e.Value.Duration.TotalMilliseconds,
status = e.Value.Status.ToString(),
description = e.Value.Description
}),
totalStatus = r.Status,
totalResponseTime =
r.TotalDuration.TotalMilliseconds,
}, jsonSerializerOptions);
await c.Response.WriteAsync(result);
};
}
}
}
So it just pings 3 addresses and I can't see advantages of using Microsoft.AspNetCore.Diagnostics.HealthChecks library. Is that wrong example?

Azure Logic Apps internal server error 500

Am trying to create a an azure function that is triggered in a Logic Apps,
The functions purpose is to web crawl certain web sites, take the desired information, compare that with a a SQL Server database in Azure, compare if we already have that information if not add it.
My issue is that when ever i run it I get the Server 500 error, I assume its accessing the database that cause. Help?
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log
)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string RequestBody = await new StreamReader(req.Body).ReadToEndAsync();
{
return await CrawlBlog(0, RequestBody);
}
}
private static async Task<IActionResult> CrawlBlog(int Picker, string req)
{
int BlogPicker = Picker;
string TheResult = req;
//Get the url we want to test
var Url = "";
if (BlogPicker == 0)
{
Url = "*********";
}
else if (BlogPicker == 1)
{
Url = "*********";
}
/*
else if (BlogPicker == 2)
{
Url = "https://azure.microsoft.com/en-in/blog/?utm_source=devglan";
}
*/
else
{
TheResult = "False we got a wrong pick";
return (ActionResult)new OkObjectResult
( new {TheResult });
}
var httpClient = new HttpClient();
var html = await httpClient.GetStringAsync(Url);
var htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml(html);
//a list to add all availabel blogs we found
var Blog = new List<BlogStats>();
switch (BlogPicker)
{
case 0:
{
var divs =
htmlDocument.DocumentNode.Descendants("div")
.Where(node => node.GetAttributeValue("class", "").Equals("home_blog_sec_text")).ToList();
foreach (var divo in divs)
{
var Blogo = new BlogStats
{
Summary = divo.Descendants("p").FirstOrDefault().InnerText,
Link = divo.Descendants("a").FirstOrDefault().ChildAttributes("href").FirstOrDefault().Value,
Title = divo.Descendants("a").FirstOrDefault().InnerText
};
Blog.Add(Blogo);
}
break;
}
case 1:
{
var divs =
htmlDocument.DocumentNode.Descendants("div")
.Where(node => node.GetAttributeValue("class", "").Equals("post_header_title two_third last")).ToList();
foreach (var divo in divs)
{
//string TheSummary = "we goofed";
var ThePs = divo.Descendants("p").ToList();
var Blogo = new BlogStats
{
Summary = ThePs[1].GetDirectInnerText(),
Link = divo.Descendants("a").LastOrDefault().ChildAttributes("href").FirstOrDefault().Value,
Title = divo.Descendants("a").FirstOrDefault().InnerText
};
Blog.Add(Blogo);
}
break;
}
}
TheResult = await SqlCheck(Blog[0].Title, Blog[0].Summary, Blog[0].Link); //error 500
return (ActionResult)new OkObjectResult
(
new
{
TheResult
}
);
}
public static async Task<string> SqlCheck(string Tit, string Sumy, string Lin)
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "flygon.database.windows.net";
builder.UserID = "*****";
builder.Password = "********";
builder.InitialCatalog = "torkoal";
System.Data.DataSet ds = new System.Data.DataSet();
SqlConnection connection = new SqlConnection(builder.ConnectionString);
connection.Open();
SqlCommand CheckCommand = new SqlCommand("SELECT * FROM TableBoto WHERE Link = #id3 ", connection);
CheckCommand.Parameters.AddWithValue("#id3", Lin);
SqlDataAdapter dataAdapter = new SqlDataAdapter(CheckCommand);
dataAdapter.Fill(ds);
int i = ds.Tables[0].Rows.Count;
if (i > 0)
{
return $" We got a Duplicates in title : {Tit}";
}
try
{
{
string query = $"insert into TableBoto(Title,Summary,Link) values('{Tit}','{Sumy}','{Lin}');";
SqlCommand command = new SqlCommand(query, connection);
SqlDataReader reader = await command.ExecuteReaderAsync();
reader.Close();
}
}
catch (SqlException)
{
// Console.WriteLine(e.ToString());
}
connection.Close();
return $" Success Ign +{Tit} + Ign {Sumy}+ Ign {Lin} Ign Success SQL ";
}
}
500 HTTP status code is a generic code which means that the server was not able to process the request due to some issues, First step would be to add some exception handling to your function and see if the failure occurs and where it occurs.
On Side note, you should not use HTTP client in the way used in the code, you should not new it up every time your function executes, this client should be static in nature. Refer Manage connections in Azure Functions

autodesk design automation

FATAL ERROR: Unhandled Access Violation Reading 0x0008 Exception at 1d8257a5h
Failed missing output
I finally made it work with HostApplicationServices.getRemoteFile in local AutoCAD, then migrated it to Design Automation. It is also working now. The below is the command of .NET plugin.
To have a simple test, I hard-coded the URL in the plugin. you could replace the URL with the workflow at your side (either by an json file, or input argument of Design Automation)
My demo ReadDWG the entities from the remote URL file, then wblock the entities to current drawing (HostDWG), finally save current drawing.
Hope it helps to address the problem at your side.
.NET command
namespace PackageNetPlugin
{
class DumpDwgHostApp: HostApplicationServices
{
public override string FindFile(string fileName,
Database database,
FindFileHint hint)
{
throw new NotImplementedException();
}
public override string GetRemoteFile(Uri url,
bool ignoreCache)
{
//return base.GetRemoteFile(url, ignoreCache);
Database db =
Autodesk.AutoCAD.ApplicationServices.Application.
DocumentManager.MdiActiveDocument.Database;
string localPath = string.Empty;
if (ignoreCache)
{
localPath =
Autodesk.AutoCAD.ApplicationServices.Application.
GetSystemVariable("STARTINFOLDER") as string;
string filename =
System.IO.Path.GetFileName(url.LocalPath);
localPath += filename;
using (var client = new WebClient())
{
client.DownloadFile(url, localPath);
}
}
return localPath;
}
public override bool IsUrl(string filePath)
{
Uri uriResult;
bool result = Uri.TryCreate(filePath,
UriKind.Absolute, out uriResult)
&& (uriResult.Scheme == Uri.UriSchemeHttp ||
uriResult.Scheme == Uri.UriSchemeHttps);
return result;
}
}
public class Class1
{
[CommandMethod("MyPluginCommand")]
public void MyPluginCommand()
{
try {
string drawingPath =
#"https://s3-us-west-2.amazonaws.com/xiaodong-test-da/remoteurl.dwg";
DumpDwgHostApp oDDA = new DumpDwgHostApp();
string localFileStr = "";
if (oDDA.IsUrl(drawingPath)){
localFileStr = oDDA.GetRemoteFile(
new Uri(drawingPath), true);
}
if(!string.IsNullOrEmpty(localFileStr))
{
//source drawing from drawingPath
Database source_db = new Database(false, true);
source_db.ReadDwgFile(localFileStr,
FileOpenMode.OpenTryForReadShare, false, null);
ObjectIdCollection sourceIds =
new ObjectIdCollection();
using (Transaction tr =
source_db.TransactionManager.StartTransaction())
{
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
SymbolUtilityServices.GetBlockModelSpaceId(source_db),
OpenMode.ForRead);
foreach (ObjectId id in btr)
{
sourceIds.Add(id);
}
tr.Commit();
}
//current drawing (main drawing working with workitem)
Document current_doc =
Autodesk.AutoCAD.ApplicationServices.Application.
DocumentManager.MdiActiveDocument;
Database current_db = current_doc.Database;
Editor ed = current_doc.Editor;
//copy the objects in source db to current db
using (Transaction tr =
current_doc.TransactionManager.StartTransaction())
{
IdMapping mapping = new IdMapping();
source_db.WblockCloneObjects(sourceIds,
SymbolUtilityServices.GetBlockModelSpaceId(current_db),
mapping, DuplicateRecordCloning.Replace, false);
tr.Commit();
}
}
}
catch(Autodesk.AutoCAD.Runtime.Exception ex)
{
Autodesk.AutoCAD.ApplicationServices.Application.
DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.ToString());
}
}
}
}

VCR for ServiceStack's JsonServiceClient

The Ruby VCR library enables you to "Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests."
I'd like to create something similar using ServiceStack's JsonServiceClient, but I can't get it to work. My most recent failed attempt follows. I'd like to either make my current attempt work, or suggestions on another approach that will work.
public static class Memoization
{
public static Func<T, TResult> AsCached<T, TResult>(this Func<T, TResult> function)
{
var cachedResults = new Dictionary<T, TResult>();
string filename = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + (typeof(TResult)).Name + ".jsv";
var serializer = MessagePackSerializer.Create<Dictionary<T, TResult>>();
if (cachedResults.Count == 0)
{
////// load cache from file
using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
cachedResults = serializer.Unpack(fs);
}
}
return (argument) =>
{
TResult result;
lock (cachedResults)
{
if (!cachedResults.TryGetValue(argument, out result))
{
result = function(argument);
cachedResults.Add(argument, result);
////// update cache file
using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
serializer.Pack(fs, cachedResults);
}
}
}
return result;
};
}
}
class MemoizeJsonClient<TResponse> : JsonServiceClient, IServiceClient, IRestClient
{
private Func<IReturn<TResponse>, TResponse> _getCached;
private JsonServiceClient client;
public TResponse Get(IReturn<TResponse> request)
{
if (_getCached == null)
{
Func<IReturn<TResponse>, TResponse> func = GetImpl;
_getCached = func.AsCached();
}
return _getCached(request);
}
private TResponse GetImpl(IReturn<TResponse> request)
{
return client.Get(request);
}
public MemoizeJsonClient(string BaseUri) {
client = new JsonServiceClient(BaseUri);
}
}
Called like this:
[Test]
public void TestReports2()
{
string Host = "http://localhost:1337";
string BaseUri = Host + "/";
List<Options> testcases = new List<Options>();
testcases.Add(new Options("Name", "20130815", "20130815"));
foreach (Options options in testcases)
{
TransactionsReq transRequest = new TransactionsReq();
transRequest.source = "Source";
transRequest.name = new List<String>(new string[] { options.Name });
transRequest.startDate = options.StartDate;
transRequest.endDate = options.EndDate;
MemoizeJsonClient<TransactionsReqResponse> client = new MemoizeJsonClient<TransactionsReqResponse>(BaseUri);
List<Transaction> transactions;
TransactionsReqResponse transResponse = client.Get(transRequest);
transactions = transResponse.data;
}
}
But I get the following error:
System.Runtime.Serialization.SerializationException occurred
HResult=-2146233076
Message=Cannot serialize type 'ServiceStack.ServiceHost.IReturn`1[ImagineServerWrapper.DTO.TransactionsReqResponse]' because it does not have any serializable fields nor properties.
Source=MsgPack
StackTrace:
at MsgPack.Serialization.SerializerBuilder`1.CreateSerializer()
InnerException:

Credentials prompted while rendering a remote ReportViewer control in MVC4

I am creating one web app (mvc 4) to authorize customers (using membership provider) to view the reports(SSRS 2008) for which they are registered but they don't have any kind of access to our report server.
Based on the link How do I render a remote ReportViewer aspx page in MVC4?, I have implemented Elsimer's latest answer and it works well in downloading as a pdf file.
But when I try to render as html using the same code mentioned in the above link it is asking for the windows credentials to access the report server.
So I am giving a general credential which has all access to all the reports in the reportserver through the code. but it is still asking for the credentials for the report server when they try to view as html in the client side browser. Report is getting rendered but the images and graphs are not rendering without credentials.
Please advise, I have tried many things to solve this. but no luck.
My controller and credential class code as follows:
[Route("report/MonthlySummary")]
[ValidateAntiForgeryToken]
public ActionResult MonthlySummary(MonthlyReportParameters model)
{
if (ModelState.IsValid)
{
try
{
var actionType = model.ActionType;
if (actionType == "View Report")
{
return ExportMonthlyReportToHtml(model);
}
else if (actionType == "Download pdf report")
{
return ExportMonthlyReportToPdf(model);
}
}
catch (Exception ex)
{
//Logging errors
}
}
return null;
}
private ActionResult ExportMonthlyReportToHtml(MonthlyReportParameters monthlyParams)
{
ReportViewer reportViewer = BuildMonthlyReport(monthlyParams);
reportViewer.ServerReport.Refresh();
byte[] streamBytes = null;
string mimeType = "";
string encoding = "";
string filenameExtension = "";
string[] streamids = null;
Warning[] warnings = null;
//To view the report in html format
streamBytes = reportViewer.ServerReport.Render("HTML4.0", null, out mimeType, out encoding, out filenameExtension, out streamids, out warnings);
var htmlReport = File(streamBytes, "text/html");
return htmlReport;
}
private static ReportViewer BuildMonthlyReport(MonthlyReportParameters model)
{
ReportViewer reportViewer = new Microsoft.Reporting.WebForms.ReportViewer();
try
{
var rptParameters = new List<ReportParameter>
{
//Building parameters
};
reportViewer.ProcessingMode = ProcessingMode.Remote;
reportViewer.ServerReport.ReportPath = "/reportFolder/reportName";
var reportServerUrl = ConfigurationManager.AppSettings["ReportServerUrl"];
if(!string.IsNullOrEmpty(reportServerUrl))
{
reportViewer.ServerReport.ReportServerUrl = new Uri(reportServerUrl);
}
reportViewer.ServerReport.ReportServerCredentials = new ReportServerCredentials();
reportViewer.ServerReport.SetParameters(rptParameters);
}
catch (Exception ex)
{
var errorMessage = ex.Message;
//TODO: handle errors;
}
return reportViewer;
}
public sealed class ReportServerCredentials : IReportServerCredentials
{
public bool GetFormsCredentials(out Cookie authCookie, out string userName, out string password, out string authority)
{
authCookie = null;
userName = null;
password = null;
authority = null;
return false;
}
public WindowsIdentity ImpersonationUser
{
get
{
return null;
}
}
public ICredentials NetworkCredentials
{
get
{
string userName = ConfigurationManager.AppSettings["ReportUserName"];
if ((string.IsNullOrEmpty(userName)))
{
throw new Exception("Missing user name from web.config file");
}
string password = ConfigurationManager.AppSettings["ReportPassword"];
if ((string.IsNullOrEmpty(password)))
{
throw new Exception("Missing password from web.config file");
}
string domain = ConfigurationManager.AppSettings["DomainName"];
if ((string.IsNullOrEmpty(domain)))
{
throw new Exception("Missing domain from web.config file");
}
return new NetworkCredential(userName, password, domain);
}
}
}
Thanks in advance,