Programmatically open an Excel document with connection to a Tabular Model - excel

I would like to create a spreadsheet programmatically with a connection to my Tabular Model that exists in an Azure Analysis Server when the user clicks on some button. Similar to the option available in Azure to View Tabular Model which creates an odc file which you can open in Excel. My application is hosted on Azure and I am using .NET Core 2.2 as back-end.
I am quite clueless how can I achieve this. Has anyone managed to implement such functionality?

The simplest thing is to just generate and deliver an odc file, which will open with Excel.
First create an .odc file pointing to your AAS server, per docs: Create an Office Data Connection file.
Then add that .odc file to your web app, and serve it through a controller like this:
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Text;
namespace WebApplication4.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class OdcController : ControllerBase
{
private IHostingEnvironment hostingEnvironment;
public OdcController(IHostingEnvironment env)
{
hostingEnvironment = env;
}
// GET api/values
[HttpGet]
public ActionResult Get()
{
var fp = Path.Combine(_env.ContentRootPath, "model.odc");
var odcText = System.IO.File.ReadAllText(fp);
//optionally modify odcText
return File(Encoding.ASCII.GetBytes(odcText), "application/octet-stream", "model.odc");
}
}
}

Related

Get Revit model as Autodesk.Revit.DB Document class using Desktop Connector

I'm looking for a way (may not be possible) to get a Revit file from the Autodesk
Desktop Connector to a Document class so I won't have to use the cloud API's.
The code below doesn't compile but does represented the genral idea, any thoughts ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Autodesk.Connectivity.WebServices;
using Autodesk.Connectivity.WebServicesTools;
using Autodesk.Revit.DB;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
// Set up connection to the Autodesk Desktop Connector
WebServiceManager serviceManager = WebServiceManager.GetServiceManager();
string ticket = serviceManager.SecurityService.Authenticate();
// Get the list of files in the Autodesk Desktop Connector
File[] files = serviceManager.DocumentService.FindFiles(ticket, "*.rvt");
// Open the first Revit file in the list
Document doc = Autodesk.Revit.ApplicationServices.Application.OpenDocumentFile(files[0].path);
}
}
}
No, you cannot access the Revit Document class from such an external context. To access it, you need to be in a valid Revit API context:
Use of the Revit API Requires a Valid Context
Valid Revit API Context and External Events
Such a context is either provided by running Revit.exe on your Windows desktop and installing an add-in implementing the requisite Revit API event handlers, or by making use of the Autodesk Platform Services APS (formerly Forge) Design Automation API.

Xamarin.Android Cannot pull table from Azure database in Android 10 Q

I did read that because lack of support for Netcore 2.1 the
myItemsList = await App.MobileServiceAndroid.GetTable<MyTable>().ToListAsync();
does not currently work on Android, and there is a workaround to pass an HttpClientHandler() in the constructor of the MobileServiceClient, and so I did like this:
public static MobileServiceClient MobileServiceAndroid =
new MobileServiceClient(AppConstants.AZURE_PRODUCTION_WEB_API_URL, new HttpClientHandler());
But this is incomplete,its still not working, what exactly do I have to do to make this work, any guidance is much appreciated.
From my understanding, you are using a Forms/PCL project whereas the other solution was implementing this code inside their Android project.
For you, once you add using Xamarin.Android.Net; to the class, you should be able to just do this:
public static MobileServiceClient MobileServiceAndroid =
new MobileServiceClient(AppConstants.AZURE_PRODUCTION_WEB_API_URL, new AndroidClientHandler());
Most likely you might have issues getting that using statement, for that you will have to follow steps shown here, or customized for you in the following steps:
Add the Xamarin Forms project to all your projects.
Create an interface ICustomClientHandler in the Core project
using System;
using System.Net.Http;
namespace Test
{
public interface ICustomClientHandler
{
HttpClientHandler GetHandler();
}
}
Then create a CustomClientHandler in the Droid project, which will be the Android part of the dependency service that will help you retrieve the native AndroidClientHandler
using System.Net.Http;
using Xamarin.Android.Net;
using System.Runtime.CompilerServices;
using Xamarin.Forms;
using Test;
[assembly: Xamarin.Forms.Dependency(typeof(Test.Droid.CustomClientHandler))]
namespace Test.Droid
{
public class CustomClientHandler : ICustomClientHandler
{
public HttpClientHandler GetHandler()
{
return new AndroidClientHandler();
}
}
}
Implement an iOS version as well in a similar way, but it will instead return new HttpClientHandler();
Finally, use the code as shown, in your Core project:
var clientHandler = DependencyService.Get<ICustomClientHandler>().GetHandler();
public static MobileServiceClient MobileServiceAndroid =
new MobileServiceClient(AppConstants.AZURE_PRODUCTION_WEB_API_URL, clientHandler);

setting must be in the form "name=value" in vs 2017

I have been learning the bot framework from microsoft and have been following a tutorial on pluralsight. I have made the changes to my Global.asax.cs and for some reason I keep on getting the error setting must be in the form name=value. I have no idea what to do and how to get rid of these errors. Any help would be highly appreciated.
Global.asax.cs
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// This code chunk below will allow us to use table bot data store instead of
// in memory data store
Conversation.UpdateContainer(
builder =>
{
builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
// here we grab the storage container string from our web config and connecting
var store = new TableBotDataStore(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);
builder.Register(c => store).
Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore).
AsSelf().
SingleInstance();
});
GlobalConfiguration.Configure(WebApiConfig.Register);
TableBotDataStore is for Azure Table Storage, and it seems you are using some sql connectionstring. You would usually have that connection string in the AppSettings section, not the ConnectionStrings section (yes, the names are a bit misguiding here).

Restart Web/Api-App on Azure programmatically

How can I restart Web-Apps and API-Apps on Azure programmatically?
(I'd like to call it from another API-App within the same App service plan.)
There's also the "Microsoft Azure Management Libraries" Nuget that allows you to work with Azure services from inside of applications.
See this page for an example on how to create new web sites from inside of an Azure Web site. Restarting web services work in a similar way to creating new services. See this page for a list of available web site related methods.
Also, for authenticating is used certificate base authentication, see this page for more details on that.
Bellow is a short command line program that will restart all websites in all the webspaces you got in your Azure subscription. It works kinda like an iisreset for Azure Web Sites.
The code is based on samples taken from the links earlier mentioned:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Management.WebSites;
using Microsoft.WindowsAzure;
using System.Security.Cryptography.X509Certificates;
using Microsoft.WindowsAzure.Management.WebSites.Models;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var subscriptionId = "[INSERT_YOUR_SUBSCRIPTION_ID_HERE]";
var cred = new CertificateCloudCredentials(subscriptionId, GetCertificate());
var client = new WebSiteManagementClient(cred);
WebSpacesListResponse webspaces = client.WebSpaces.List();
webspaces.Select(p =>
{
Console.WriteLine("Processing webspace {0}", p.Name);
WebSpacesListWebSitesResponse websitesInWebspace = client.WebSpaces.ListWebSites(p.Name,
new WebSiteListParameters()
{
});
websitesInWebspace.Select(o =>
{
Console.Write(" - Restarting {0} ... ", o.Name);
OperationResponse operation = client.WebSites.Restart(p.Name, o.Name);
Console.WriteLine(operation.StatusCode.ToString());
return o;
}).ToArray();
return p;
}).ToArray();
if(System.Diagnostics.Debugger.IsAttached)
{
Console.WriteLine("Press anykey to exit");
Console.Read();
}
}
private static X509Certificate2 GetCertificate()
{
string certPath = Environment.CurrentDirectory + "\\" + "[NAME_OF_PFX_CERTIFICATE]";
var x509Cert = new X509Certificate2(certPath,"[PASSWORD_FOR_PFX_CERTIFICATE]");
return x509Cert;
}
}
}
Another alternative, if you can't find the function you need from the above mentioned library, you can also run powershell commands programmatically from inside of your application. You most likely will need to move, the application that is supposed to run these cmdlets, to a virtual machine to be able to load the needed powershell modules. See this page for more information on running powershell cmdlets programmatically.
You can use Powershell to do this. The relevant commands are:
Start-AzureWebsite -Name “xxxx”
Stop-AzureWebsite -Name “xxxx”
You can find help on these commands at the following links:
https://msdn.microsoft.com/en-us/library/azure/dn495288.aspx
https://msdn.microsoft.com/en-us/library/azure/dn495185.aspx
I think handling the base REST API is much better option. The Azure SDK changes quite a lot and lacks good documentation.
Here is an up-to-date sample code:
https://github.com/davidebbo/AzureWebsitesSamples/
You can adapt it to your needs.

Where to store ODP.NET Managed Driver Connection Strings?

Finally got ODP.NET configured and the Oracle.ManagedDataAccess DLL referenced in the project.
I was testing with a TNS connection in the code behind in a WPF project (see below).
This question is probably elementary, but I can't find any good information on this, as all examples/jump-starts show embedding the connection string like this.
Is there a better (more common) way to store the connection string for ODP.NET to make it easier to maintain (i.e. it should be a configuration change that doesn't require completely rebuilding the code if it should change)? For example, similar to storing in app.config for SQL Server and IIS?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Oracle.ManagedDataAccess.Client;
using Oracle.ManagedDataAccess.Types;
namespace TEST
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private OracleConnection con;
public MainWindow()
{
InitializeComponent();
try
{
con = new OracleConnection("User Id=*****; Password=******; Data Source=******");
con.Open();
}
catch (OracleException oracleErr)
{
MessageBox.Show(oracleErr.Message);
}
finally
{
con.Close();
}
}
}
}
In case you used the tnsnames.ora from the Oracle Client for the unmanaged version then for the managed version you just have to copy the tnsnames to your project directory.

Resources