>> Good morning, good afternoon, and good evening depending
on what times on your on. Thank you so much for
joining us everyone. My name is Kelly Kaye. I'm the MVP lead at
Microsoft for Power BI, also Power BI Community Manager, and I look after webinars
and user groups as well. Today, we have the pleasure of
the amazing Ted Pattison who, I'm very proud to say, we hired
here at Microsoft recently. Ted has been a MVP for 12 years on SharePoint and
three years on Power BI, and now we have him in the
customer advisory team, and Ted has kindly offered to do a Dev Camp series
for us once a month. This is the first session and now
I'll just hand it over to Ted. So thanks again Ted. >> Thanks Kelly very
much. Welcome everybody. I'm excited about this new
webinar series Power BI Dev Camp. This is our very first session. I want to quickly point out a
particular portal that we have here. Let's say that I just quickly go over to this particular portal here. What I'm trying to show here is that, for each one of these
sessions that we have, we basically have a
little page for it. For instance, if you want
the PowerPoint slides, if you want the tutorial, and we have a nice big long
tutorial that you can go through. If I go ahead and just
open this thing up with Word so I can show
you what it looks like. It's basically about 37 pages of just stepping through and doing
what I'm going to be doing here. Once again, there is other pointers
to some of the code samples, and to a couple of different other
resources that we have there. Let me go ahead and move
back to our slides. >> [inaudible]. We're going to have the links in
the community there. I think you, and Sandy, and I are going to set up an area to have that in the
community, I think. I'll pop the links in there
at the end of this call. >> That would be great if
you could just go ahead and put those into the
chat for everybody. >> Awesome. >> What we're going to work
through now is basically, let me just introduce the tutorial. We're here for Power BI development, and one of the big areas in Power BI development
is Power BI Embedding. For those of you who might not have worked with Power BI Embedding, let me just give a
real quick overview. You create a browser-based
application, and one of the things that
your application has to do, it has to interact with Azure AD, maybe to authenticate the user, maybe to authenticate the app
with an app-only identity, and get an access token. We need an access token
because we have to call the Power BI service to
get embedding information. For instance, I want
to embed a report, so I need the [inaudible]
for the report ID. I need something called an embed URL, I need some type of security token. The idea is we pass all that
information to the browser, and it's a one-two punch. The first punch is going
to the Power BI service, getting what you need, passing
it back to the browser. The second punch is writing
client-side code in JavaScript or maybe TypeScript
that actually does the embedding, and takes the data and behind
the scenes creates an iFrame. What it's going to
need is, after you've done this dance and you've
done the embedding, your report is connected from your custom webpage right
to the Power BI service. If someone clicks on a bar in a
bar chart or clicks on a slicer, the interaction doesn't go
through your application, it's directly between that
report and the Power BI service. Now also, there's two
types of embedding. I've given a lot of talks about embedding so I'm not going to go into all the details that
I've gone into before. But User-Owns-Data embedding
is when you authenticate the user and you use the user's access token to
talk to the Power BI service. It means that every single
user needs a Power BI license. If your content is in
a dedicated capacity, it could basically be a
free license for Power BI, and if it's not, it has
to be a pro-license. Now, there's another model
which is called App-Owns-Data, which is popular with ISVs
because you can reach users that don't have any Power BI license and are completely
unknown to Microsoft. Now, in our tutorial today
what we're going to do is, we're going to concentrate on
the User-Owns-Data sample. Now, what I'm going to do? I'm going to go ahead
and move back here, and what I'd like to do is, go into my samples and I'm going to take this
one particular sample, which is the User-Owns-Data sample. Here's a sample that I just
want to run for a minute just to show you what the
application is going to do. Here's what we're working
to build for the next hour. Basically, we're going
to run this application, and so we want to have a nice
sign on experience for the user. The user signs on, we say hello to the user, and then what the
user is going to do, is go to this one particular page. Now, let me just go on a tangent and go over just through
the Power BI service, and you can see that I have a personal workspace and it's got
a couple of different reports. We've got a couple of
different workspaces here. So when we use this application, one of the things that
we should be able to do, is give the user the chance to move between the different workspaces
that that user is in. Then once the user gets there, allowing the user to open reports, to take a report that has already been created
and go into edit mode, and also to create new reports. That's what this
application is going to do. This demo goes a little bit further, where it's also possible for
you to create a new workspace. It's a Thursday afternoon so perfect time to create
a workspace name Bob. The application allows us to create a workspace and to even
upload some sample content. Now when we go to this
brand new workspace that has just been created, your custom app can basically
do all the work to create workspaces and add content behind the scenes for your particular users. What I wanted to do is, just I
wanted to go through and show you a quick demo of what
we're going to be building. But now, here's the tutorial. Now there's another
GitHub repository, github.com/PowerBiDevCamp/NetCore-UserOwnData-Tutorial. If you just go to that one
site, the links there. But the idea is that, there's either a Word document or a PDF file and you'll
open that up and you'll start working through
our particular lab. Now, here's the flow of the exercises that we're
going to go through. Exercise 1, we're going to create a new.Net core web
application with MVC. We're going to implement user
login with this new neat library, Microsoft.Identity.Web, we're going
to call the Power BI service, we need to add some JavaScript
code to embed the report. As we get to exercises five
and six, we're going to say, "JavaScript's just not cool enough, I'd rather program in TypeScript." We're going to have to add support
to our.Net project so that we get the benefits of
being able to program in TypeScript and get things
like compile time, type checking, and
basically strong typing that goes way beyond what
we can get with JavaScript. That's our mission. Also note
that when you do this project, one of the things that
we have you do is, if I come back here, there is a particular link. I'm going to go ahead
and copy that link. Now, if I basically go to the browser window and I'm
going to paste that link in. I want to give you the files
that you need on your machine, which is something which is
called the StudentLabFiles. If I now go, and I'm going to be doing the lab
and just see DevCamp, the idea is that when you
work with a PDF file, you can copy and paste
code out and put it in, and for some people, it's a wonderful experience, and for other people
it's horrible because the line breaks aren't there. Anything that you need
to copy and paste, there is a text file here in the StudentFiles for
you to be able to use. Now, let's get into
our first exercise, and the first topic which is
developing with.NET Core. Now, the first thing
we have to do is, we have to install the.NET Core SDK, it installs the.Net Core Runtime, it installs some developer
project templates. Once we've installed the SDK, there is this new
command line utility, which is called dotnet, D-O-T-N-E-T, and we're going
to be able to run that, and we're going to be able to create
a new particular application. Now before we get into it, there's one more really important
developer concept in .NET. If you've never done .NET
Core before you might not understand and that's
dependency injection. The idea of dependency injection
is that there's a set of services that you'd like to use, but you don't have to
go track down and find the service or find a class
and create an instance of it. Instead, what we're going to do is we're going to go to the
constructor and we're just going to basically add a
parameter of a specific type. The way I like to think about
it is imagine we have a doctor who's taking out someone's appendix. When she's ready for a scalpel, she doesn't turn around
go look for a scalpel, she just says, "Scalpel." Then when she wants
forceps, she says, "Forceps," and the system or someone behind her just
gives her what she needs. So the idea in.NET Core
there's registered services and when you want to
use one in one of your classes, you basically just add a
parameterized constructor. The.NET Core runtime takes care of creating an instance
of the service, on-demand if necessary, in handing
you a particular reference. What we're going to do in exercise
1 is I'm going to open up this particular
PowerShell script that's going to program against the.NET CLI. We're going to run the PowerShell
script and create a new project. Sounds good. Let's go back here. I'm going to create a new folder and that folder is going
to be called UserOwnsData. Then one thing that I'm going to do is I'm going to go grab two files and I'm just following along with what the Lab is going to
be telling you to do. Inside here, I now have this
particular.NET Core project. What I'm going to do is I'm
going to open this thing up. Once it gets ready, I'm going to
go ahead and remove the script. We go ahead and run
this and lo and behold, my project directory
fills up with files because basically the.NET
Core runtime is running. Note that we're going
to get rid of one of the packages that was
automatically added. We're going to add this new package which is called
Microsoft.Identity.Web, and its little brother, which
is Microsoft.Identity.Web.UI. Now, let's go back here and
take our particular project, and I'm going to go ahead
and just open this thing up with Visual Studio Code. Now here is my particular project. I can use Visual Studio
Code to start editing that. That was our first step, which was basically
creating the project. One other thing to note
is you go to the Lab, there are two essential Visual
Studio Code extensions: the C# one for Microsoft and
the Debugger for Chrome. You can add whatever other
extensions make you happy, but at a very minimum, add these two extensions as you're doing this.NET
Core development. Now let's move on to
this other thing, which is basically the
Microsoft.Identity.Web. What this does for me is that it provides an
authentication library. It's brand new. It's so new, it's not even released yet. What is Microsoft.Identity.Web? It's a set of components
and classes created by the Microsoft Identity Team
to assist web developers. It's used to perform authentication in web applications and Web APIs. It is not just going to implement the OpenID Connect protocol
but it's also going to make it very easy for you to
acquire access tokens. If that's not enough, it's going
to add support to implement token caching so that behind the scenes when
you've got an access token, there's going to be refresh tokens
that are automatically cached. When you want to get an access
token an hour-and-a-half hour later after your access
token has expired, there's just code
that's automatically going to take the refresh token and redeem it to get a new access
token and hand it back to you. Now, a couple of things to note. This is a library that's been built
by Microsoft for.NET Core 3.1, that's what we're using
today, and.Net Core 5. It will be the preferred library. It's currently in preview, and Microsoft is scheduled
to release this. When they releases.NET 5? My best guess is in
November of this year. I wanted to add a link down here
just in case you want to go see, there's a wiki on the
GitHub repo where the team has their code and
basically puts their documentation. Now, why is this library good? Generally, I won't push you to use a preview component
as I do these demos, but unfortunately there's not a
good pre-existing alternative. Let's say that I wanted
to do the same thing but before we had
Microsoft.Identity.Net. Many of you have probably
moved from ADAL to MSAL, to Microsoft.Identity.Client,
and that helps you acquire access tokens
and cache access tokens. But when it comes to actually
implementing OpenID Connect, it provides nothing for you. Generally, what you need
to do is get middleware. If we were back in.Net Framework, I'd add both Microsoft.Identity.Client
to get access tokens, and I'd add all these OWIN components
to implement OpenID Connect. What's really neat is that
now all this gets replaced by Microsoft.Identity.Web
and the part that helps you implement OpenID Connect is the
Microsoft.Identity.Web.UI. If we go through here, what we'd like to do in this section is to go through what you're
going to do inside of the Lab. Let's start by creating
an Azure application. I'm going to go back and I'm
going to go to the Azure portal. In the Azure portal, you can see that I've got two
applications registered here. But now let's go back and
we're going to go here, and there is this PowerShell script called CreateAzureADApplication. I'm going to go ahead
and open this thing up. Then I'm just going
to put a number 2 in the application display
name so you can see the difference between the one I've already registered in this one, and now I'm just going to go
ahead and run the script. You can see that up top, it's
calling Connect-AzureAD. I'll go ahead and I'll log in
as TedP@powerbidev.camp.net. Now that I have logged in, it should be able to run this script. Ted, do you remember your password? I think so. It's going
to run the script, and then when it's all done, it's going to spit
out this text file. Now, let's go back here. I'm going to go ahead
and do a refresh. I hate going and creating
these things by hand. The idea is that if we
have a PowerShell script, let's go back and take a look at it, my PowerShell script and
create an application secret, it can then create the application, and then create this output file. But the idea is that
after you run that, you have this particular file. Let's go back to our project
now, the UserOwnsData. Notice that when we created this, they gave me this file. But obviously, they can't
give me anything specific, so they had to put some
placeholder stuff. But the idea is that I
can now just take what my PowerShell script put out
and put that right here, and now I've got what I
need in the app.json. Let's keep going
through with this demo. Once again, I'm going
to take you through exactly what you're going to
do if you do this tutorial. The first thing is to run
the PowerShell script. It creates the particular Azure
AD confidential application, and then it just gives
you a JSON fragment that you copy into appsettings.json. So good, so far. The
next thing that we have to do is we have to
make a couple of changes. Back here, let's go to Startup. If I go to Startup, one of the things that
you're going to see is that there's an old
library we got rid of. I'm going to go ahead
and get rid of that. Then I'm going to cheat
here just for a second because I want to go down and get these using statements that
we're going to take from here. Now I'm going to go down here. No need to remember this, there's
step-by-step instructions. What we're going to do
is we're going to go to this older place right here. Here's the library we got rid of. What we're going to
do is we're going to say Add and we're going to look for MicrosoftIdentityWebApplication
and we're going to go ahead and pass in the configuration object. That's all you have to do to turn
on the authentication service. There's one more thing that
we're going to have to do and that is we have to register that we want
the UI for OpenID Connect. The way I'm going to have you do this inside of this particular Lab, let me just make sure
this thing compiles, is we're going to say,
var mvcController equals. Now that we've got this
particular object, I'm going to go down here, and now, what we're going
to do is we're going to add the Microsoft Identity
UI one more time. What's neat about this
guy right here is that it registers an
account controller behind the scenes, you
don't even see it. Now, once we've gotten
to this point right here and we basically
configure the new Microsoft.Identity.WebAuthentication
service and we've registered it for the endpoints that are needed for OpenID Connect, well, the next thing we're
going to do is we're going to go to the LoginPartial. Once again, let me encourage you, if I'm here in DevCamp and then
I go back here and I'm going to go and just grab this
value from inside here. Now, if we go back here, we're going to go into "Views", we're going to go into "Shared", and there's this partial view. Notice that they're still setup for the older library that used Azure AD. So what we're going to do is
we're going to replace it, and now, there's going
to be an ASP.NET area, Microsoft Identity, there's the account controller
that's automatically registered and now there's
both SignIn and SignOut links. Now, just to get exercise
two up and going, a couple of other things that
we're going to do is I'm going to make a quick change
into the Controllers class. So let's say we go
back to Controllers, and what I want to show
you here in Controllers is that we're going to
have two different pages, we're going to have Index and
we're going to have Embed. Now, note that when
you create a project, it automatically gives you index and privacy so I'm just
going to have you, instead of creating
a new one just take Privacy that we're not using
and change that to Embed. We'll say something like, "Got here". But the key thing I want to show here is this notion
of a secured route. That is when we
authenticate the user, the MVC authentication system
is going to know that. So when you create a class, you can say everything in there
has the authorize attribute, meaning it's a secured page, you can't get there until you login. However, one thing they do
by default that I don't like is they make it so you
can't get to the homepage. So we're going to say allow
anonymous to get to the homepage. There's two more things
that I'm going to have to quickly replace here before
I do this next demo. We gave you some
pre-copy and paste code so that you can go to
the site.css file, and now we have some very pretty CSS. Then also, we're going to go
into the "Shared" folder, we're going to take the layouts. We'll go ahead and get rid of that, and we're just going to replace
layouts with our own code. Now, let's go ahead and see
where we've gotten so far. So what I'm going to do is I'm
going to go ahead and hit the "F5". As we hit the F5 key, if it's the first time
we've done something, it basically says, "Hey, you're not setup for debugging,
pick an environment." I'm going to pick.NET Core. Note that when you pick.NET Core, it automatically adds to essential Visual Studio
code debugging files. The idea is that now
that we have done that, we should now be able to run
this particular project. Once we run this particular
project right here, what I'm going to do is I'm going to, quickly move over to "Solution", "Excercise2", and now, let's go
ahead and run this right here. I think I have this running
in multiple places. So there's a 101 error by Ted. Don't try to run two different
sessions at the same time. Let's try it one more time just so we can get
to where we should be. So here, we have a sign in link. Note that with a sign in link, you can get to the homepage
and you're not authenticated. Then a user click sign in, we should be able to
sign in and sign out. Also, I'm going to sign out. Let's go back here. We've basically got these
links to sign in and sign out. One other point is that
inside the ASP.NET Core user, you can also take attributes,
that's how I can say, "Hello," and reference
the user by their name. But what we want to see
here is we have two routes. If you look at this code right here, what you can see is on the homepage, it's very easy for you to write some content for what the user sees when the
user is not logged on, click, "Sign in," and the user clicks and signs in and goes to
that particular page. What we should see there
is that now your code, you can have conditional HTML output
depending on who the user is. The last thing I want to show with
this particular demo is that if a user is not signed in but a user clicks to go to a page that's secure, right here, what we
see is that because this page over here does not
have the AllowAnonymous, you can't get there
unless you logged in. But what's really neat is
you can just provide a link, the user tries to get to Embed page, and ASP.NET Core just
authenticates the user on the way, but still does the courtesy of dropping the user in that
page when the user is done. Now that we've seen that, we've seen run up and going, a quick word about Visual Studio
versus Visual Studio code. Let's go ahead and kill
this project for a second. Let me go back here, and if I go to my solution here, notice that it's got a csproj file. I can simply open that up
with Visual Studio Code, or if I'm old school, I'd probably use Visual Studio, I can, and the only big difference between the two is that Visual Studio code works
with project files, doesn't care about solution files. With Visual Studio itself, you're going to have
to select the project, and then after you
select the project, you can basically do
a "Save," and now, you have a project file inside there. But the idea is that you are fine to start this thing up and if you'd rather do your development
with Visual Studio, instead of Visual Studio Code, that's up to you. Let's keep going. We're making
some good time through here. Now, what we'd like to do is look
at calling the Power BI service. So far, we've authenticated the user, but the next problem we
have to solve is leveraging Microsoft.Identity.Web
to get access tokens. Now, there's two or
three background slides here on the Power BI service API, I'm going to go through
pretty quickly, they're here for your reference. But the Power BI service API, there's a REST-based API that
supports OAuth and OpenID Connect, and it allows us to
call into Power BI and automate things like uploading PBIX files or getting
data for embedding. Now, if you're not using.NET and you don't have
a library that helps you, you have to do the HTTP requests and handle the responses yourself. So here's an example of just
doing raw requests inside there, and you can see that we're
working way down at this level, creating HTTP requests, making the call across
the network and doing things like converting JSON
back into a C-Sharp object. One of the things that we like
doing if we're using the.NET framework or.NET Core is
using the Power BI SDK. The idea is that your
C-Sharp code will access this library
that abstracts away you having to execute HTTP requests and convert back and forth
between C-Sharp and JSON, so it's very recommended
if you're using.NET. Also, the Power BI.NET SDK lives
on top of the Power BI service. We've gone through version 1, version 2, and version 3, and it's not the version of the
underlying rest API down below, that really hasn't changed, it's just the.NET
wrappers have changed. We really encourage you
to move to version 3. So basically, when you use it, you have a version that starts
with 3 because there's lots of features that aren't supported
in version 2 and earlier, like doing service-side
generation of PDF files, or what we're going to look at
the end of this session which is working with multi-resource
embed tokens. Now, in this exercise, what we're going to do
is we're going to create a new class named PowerBiServiceApi. That's we're going to write our code. We're going to leverage
Microsoft.Identity.Web and the token acquisition service. We're going to call onto Power BI and get the
embedding data we need, and we're going to pass the
embedding data to the report. Let's go ahead and move back here. Now, instead of doing
demos from scratch, I'm just going to open up some
of the solutions that we have. I'm going to go ahead and
open up the solution tray. What we're going to do
is we're going to go and create a new folder
called Services. We're going to create
this class in there, which is the PowerBiServiceApi. Here, what we're going
to do is we're going to use dependency injection
to get two things. I want the configuration object, and the one reason that we like that, if I go back here, in addition to the Azure AD data, we've also put here the service
root URL of the PowerBiServiceApi. The reason I've put this as a configuration option
is that because when you program against the Power BI
public Cloud, that's the value. But if you're going against
the Government Cloud or the German Cloud, or one of the other Clouds, this value will be different. I just wanted to make it
a configuration value. The first thing that we get by dependency injection is
the configuration object. Here's the second thing we get, and here's where we're leveraging
Microsoft.Identity.Web. I just want the token
acquisition service. I basically just create a variable based on the
token acquisition service, I add something into the
constructor and now I've got it. Now, if I go back to the
slides for a second, the next thing we have
to do is we have to go back into the startup, and what I showed you
earlier is we just use this one method right
here, which is the first one. But now we're going to add two more things:
EnableTokenAcquisitionToCallDownstreamApi, and notice that you have
to pass some scopes, and then AddInMemoryTokenCaches. Here's where Microsoft.Identity.Web
is fantastic. If I just want to do demos, I'm just going to use
the InMemoryTokenCache. The idea is it will cache tokens
in memory behind the scenes. They also have things
that you can use to plug into SQL Server and use
a persistent cache. Once again, as they're creating
Microsoft.Identity.Web, they're trying to take
a lot of the pain out of implementing token caching. The second thing you see here is, we're also going to say
services AddScoped, We're going to take this
class that we're creating, the PowerBiServiceApi,
and we're going to add that as a registered service. Now, a couple of
things that you'll see here is that if you
look at this code, Power BI, when I get a user token, we need to have a set of required permissions or
delegated permissions. You can see that here are the permissions that my
application is going to need. But at the end of the day, when it's time for me
to get an access token, this.tokenAcquisition get token for user async and you pass your scopes. Hey, how about all that builder stuff that we had in Microsoft.Identity.Client?
That's all gone. What's really nice is it's like Microsoft.Identity.Client
sits behind this library, but this library makes it
incredibly easy to use. One of the things that you're going
to see is tremendous value in Microsoft.Identity.Web of solving
some very difficult problems with an absolute
minimal amount of code. Now, for our first example, we're going to call GetReport. What we're going to do is once we
got this PowerBIClient object, we're going to call
our first call from the PowerBiServiceApi
get reports in group. We're going to take this data. Once we've got that method, we then go to the HomeController. Now, here we're using
dependency injection. In the PowerBiServiceApi class, I use dependency injection to give me the token
acquisition service. Now, in the controller, I'm using dependency injection
basically to get my class, the PowerBiServiceApi, which
then allows me to call this down here and get some data
and basically pass a throw. Once again, understanding
dependency injection, how that works is pretty key to
mastering.NET Core development. Now, let's go back here. What you can see here is
we're going in baby steps. This time when I look at embed, let's go ahead and
run this application. I'm going to call across the network. I'm going to get data for
one particular report. But we're not going to use
JavaScript until the next demo. But here you can see that I can get all the demo and at least
present it on the page. Here's the data that we need. Now, we're going to go up into the
next part where we're going to bring in the client-side code and programming the Power
BI JavaScript API. Now, when we start working with this, what we're going to be doing here is we're going to add
some script links, and we have to add one
script link to bring in the Power BI JavaScript
API, which is powerbi.js. We're going to create a view model to pass the embedding
data to the browser, and we're going to write
a little JavaScript code to embed a report. I'm going to go ahead, and
then I'll switch over. If I go now to Exercise4, and let's go ahead and open
up the solution to that, what we're going to see here is that now if I look at the embed view, you can see here a couple
of things we're doing. One is we're adding a link to
the JavaScript API for Power BI. Second, I'm taking the values that we got from the call
to the PowerBiServiceApi, and I'm just creating a
little JavaScript object on the page called the viewModel, and then after that we have embed.js. In Exercise4 is where you're
going to go into wwwroot, into js, and you're
going to add this file. Here's something that if I
look back here at the embed, here is a div, which is the embed container. Step number one, we'll get a DOM
reference to that container. Step number two, we're going to
take the data from that viewModel. Step number three, here's
where we're starting to program against the JavaScript API. Notice that there's this little handy JavaScript
object called models. You can say things like
models.Permission.All. Then finally, we're going
to call powerbi.embed. Let's go ahead and
run this right here, and as we run this right here, now we'll go ahead and click "Embed". Now, what we'll see is that it automatically is going to embed
that report inside there. If I go back over here and
now inside of the console, if I basically look
for the viewModel, now you can see that here's the
viewModel that we passed into the page and our JavaScript code
was just able to read that. Now, let's do one more thing. What happens if someone
takes the page and makes it small or makes it really narrow? Another thing I'm going
to have you do inside the lab is just add a little logic. Power BI is really good about reciting an embedded
report or dashboard, as long as that container is moving. If your container doesn't move, you're not going to be able
to have your board adjust. But here we're going to add
a little code so it makes the hosting window bigger or smaller. It adjusts the size
of the container and the Power BI report automatically
adapts to doing that. Exercise 4. You saw the
steps we went through. We basically create a view to
add in the link to powerbi.js. We added the viewModel to the page, and then we added our
JavaScript file and coded the JavaScript file to basically
do the implementation. Let's take a breath. Now we're going to really spin our wheels
and do something really neat, but a little bit complicated. So what we want to do is we
want to add TypeScript support. So while I can program in JavaScript, it's going to be much
better if we configure our project so that we can
write TypeScript code. When we do that, we're going to
have to add Node.js Support, and we're going to add a utility
which is called webpack. So here are all the steps
that we have to go through. What I'm going to do is I'm
going to go ahead and I am going to move over to the
solution for Exercise 5. One of the prerequisites, as you're getting ready for this lab, is to- let me make sure I
opened the correct folder. Five "UserOwnsData". What you can see here is that we
have three special files here. The first one I want to look
at is the package.json file. When we use Node.js, and that's one of the prerequisites you have to install
to go through this, it allows you to then bring
up a command line utility. So if I have a package.json file, I can call "Npm install". What that's going to
do is it's going to download a set of utilities. Notice that you have a
node modules folder. I just ran that here. For instance, here is the Node.js, and how big do those things get? They get really big. What I'm going to do is I'm going
to go ahead and delete this. When I leave my samples
up for you to download, I would never leave the
node modules folder there. But that means that the node
modules folder is gone, you just have to do a npm install and that automatically
restores those files. If I look up here, when we go ahead and
do an npm run build, it's going to run this
command called a webpack. When you look at webpack, it's a utility where you can say, what is my entry point? In lab 5, we're going to have you add embed.ts to the scripts folder, find that entry point, and basically put an
output file of embed.js. Now we're going to run
the webpack utility, and the way that you run
the webpack utility is if I call "Npm run build", that is going to run the
webpack utility right there. The idea is if I go to "Wwwroute", and I go take a look at
this file right here, that was generated by webpack. If I go ahead and delete that file, and now one more time we
do an "Npm run build", what you're going to see is that file gets created automatically on the fly by basically looking at what's
in scripts in embed.ts. If I want to go a little bit further, I can also open the
UserOwnsData.csproj file. There's two build systems. There's Node.js and
there is also the.NET. One of the things you could do is
you could open up your csproj. This is something that gets looked
at when you do a.NET build. But you can see that I can
add commands inside here. Now if someone does a
"Dotnet build", basically, I'm having it call the webpack utility that's
basically redoing that. What's neat about updating your
csproj file is now I can go back to this JavaScript file right here and I can just
basically add new code, and hit the "F5", key and
it automatically compiles into the js file before it loads in. If I go ahead and open up
this application right here, now we have switched
over to TypeScript, and what you'll see is, when you go to the
final part of lab 5, it's not really any different than
the user experience for lab 4, but we've moved from
JavaScript to TypeScript. For the developer it's
a pretty big step. Once you get to the last lab we
have you build all this out. We're just going to have you make a couple of changes
and we're going to give you some larger files. So back here, if I go
to "Student files". In Exercise 6, we're just going
to give you three big files. We're not going to have
you code it by hand. But let me show you where
we're going to get to. What I'm going to do is, let's go
back here to the final solution. I'm going to open that one up, and as I open that one
up what we should see is the finished part of the lab where when you get to the
embed page you no longer have to hard code in one report. What's going to happen, let's
go ahead and click here, is that you'll get to this
particular place right here. For some reason it wasn't
working as it should. Let me try it one more
time so we can get this to work as it should work. As this thing starts up right here, now we have the embed screen, and now somehow it's not working. So what I'm going to do is I'm
going to switch over to the sample, which is the UserOwnsData sample, just so I can move through what we're going to
have inside this application. When you get to the end of the lab, what you should be able to do is have an app that has a user experience
where you get to the embed page. This one's not working either. What's the problem? The embed URL is required
but was not found. Let me get back here. Sorry, my demo got hit
a roadblock there. I'm not sure what I was doing wrong, but the main points here is the package.json file makes
it a Node.js project. Then running NPM Install
gives you your project files. Now, one thing that's nice
about Webpack is that Webpack has dynamic module
loading to your TypeScript code. So in embed.ts you
can say things like Import star as dollar from
jQuery and Import star, and we're going to import things from PowerBIClient and Power BI models. What's neat about that is, when it compiles the code
and builds embed.js, it actually pulls code out
of those other libraries. Now, you're not going to need a
separate reference to Powerbi.js. It's automatically going to be included in that file,
it's automatically built. I went through the steps
of doing NPM run build and then also updating the
User Owns Data project. Finally, got to the part where
we're working with TypeScript. Once again, the big
benefit of working with TypeScript is we have
strongly typed programming. My variables are a type
HTML element or ViewModel, or powerbi.Configuration
or powerbi.Report. You just get a much higher degree
of compile time type checking and IntelliSense as you
move to TypeScript. Now, in Exercise 6, I had you create the ViewModel. Once again, I'm curious why
my demo stopped working. I might do one more quick test to
see if I can get this to work. Just so I can demo that. I won't spend much time here, but now we have that, if you go ahead and we run this. One more good faith effort
to succeed with the demo. Now, we'll go ahead
and click "Sign in". Now that we've signed
in will get to Embed. Somehow something broke there, but I'm going to be able to demo, one more app is going to show
you the user experience. Now, with this case right here, here's what I wanted you
to see it's not working. But the idea is that we're going to have a method that returns
just a big piece of JSON. As I do Power BI embedding, and I worry about how do we
make performance really good? We want to cut down
calls to the server. The idea is when we
get to a Workspace, we're just going to
send one big payload of data over so that client's code, can then open up reports,
create new reports. But we don't require
round trips to go back and get more
embedding information. Because we're using User Owns Data, the User Access Token from Azure AD can be used
to embed any report. Now, two more things
we want to cover. I want to show one
more demo, but first, I want to talk about
the Camper Competition. So what we like to do, is we'd like to have
all of you go through, work through this lab,
but then to take what we've done and see if you
can extend it further. Now, some of the demos
I showed you going to add the ability to create
Workspaces and upload content, but I'm going to let your creativity basically have you do what you want. But the idea is that if you create an application and you've
got some neat features, and you've been creative and
you want to show things to the peers of yours in the
Power BI Developer Community, create a 3-5 minute video, and then there's a form that
we're going to have you fill out so that you can
enter the competition. >> That's on the community, right? >> Is not on the community yet. >> Okay so we add a report. >> I'm pretty sure
you will have me put on the community before too long. >> Yes sir. >> You'll keep me in line. >> I don't know about
that because I'm learning from you,
you're the master here. >> Okay. >> Though yeah, we'll participate. >> Well, that's good. I
like people who are not experienced with keeping me in line. The best proctors we can have. >> Okay. >> I want to show one more
application here before we quit. That is, I've been looking
at User Owns Data, but now let's go ahead and load
it and one for App Owns Data. So what we have App Owns Data, let's go ahead and make sure
that this thing can load in. What we're able to do here, is when we talk to Power BI, to be able to talk not
so much as a user, but as a Service Principal. If I click over here, gosh, and what is going on? I think, discard, issue
with Visual Studio Code. So to try and save my demos here, let's go and open this thing up, this time with Visual Studio, so I can demo this. But what I wanted to show here, is let's go ahead and make sure
the application loads and it runs. I want to show as we're working
with the Service Principal, so if I go ahead and
click on "Embed", and now here's the
application that we want. We're able to move through
and do this kind of stuff. If you finish the lab, your application will look like this. Maybe a quick demo of, I can see all the reports
in my Workspaces. Also, if I go to a report, I can open it up in
Edit Mode and I'm able to make changes to that
particular report. Then we're able to hit "Save"
and actually save those back. Then what's also cool is that if you have datasets you
want expose to your user, your embedded applications can create new reports on top of
that particular dataset. Now, that we've done that, let's just add something
very simple here. We'll look at Quarters,
there's my report. Not a lot of area here, to work on reports so that's why
we have a Full Screen button. Now, as a user using my custom
application to create reports, they're able to work with that. Now, we'll do a File Save As. Let's go ahead and do a File Save As. I created a report named Bob. I grew up in Greenwich, Connecticut, lots of guys named Biff. Let's go ahead and
add the Biff Report. But what you can see here, is that we move from having a new report that's
not saved in Power BI. Now, the code saves it and then opens up the existing
report inside there. Once again, that's the things
that we want to look at. But if you've used App Owns Data, let's go back here, and first thing we'll do
is we'll look at Startup. Startup has that exact same
code that we saw before. But we don't need to add the UI piece for the user
to interactively login. Now, when it gets back here
to the Power BI Service API, what's neat is that here, tokenAcquisition instead of
get Access Token for user, let's get Access Token for App. Also, remember that there's
the value added aspect of, it's not just getting
app only Access Tokens, but it's adding Token Caching. What I see is a lot of
people that do app only, they just get a new Access Token, call across the network
every time they need one, which could be 10 times
within a single-request. Once you add the Token Caching, it Token Caches behind the scenes, and it just gives you
the same token for an hour until it wears out
and then it gets a new one. Once again, that's pretty important. Now, the one thing I
wanted to end with, we always like to end with
I got a nice beefy topic, and that is working with
Multi-Resource Embed Tokens. Now, when you use App Owns Data, you don't pass the users Access Token from Azure
AD back to the browser, you pass what's called
an Embed Token. However, early in the history
of Power BI embedding, the API only allows you to create
an Embed Token for one resource. But now with improvements to
the Power BI Service API, and new support in V3 of the SDK, we can now create
Multi-Resource Embed Tokens. Here's an example. Here, once again, inside of my application, let's go back over here, if I now go and I look at
a particular Workspace, and I've got all this
data inside here. Now, let's go over here. Then once again, let's
look at this ViewModel, so here is the ViewModel
that we're passing. The idea is that if you
can get all this data onto the Web Page and then your JavaScript
code or TypeScript code, you just take it and run with it, but we only need one token. The idea is that I want
to have this report. Then as I move from
Report 1 to Report 2, I don't want to have to
go across the network and get a new Embed Token. What this code allows you to do, and I guess I could step
through the code here. Now, when we look at this ViewModel, here, you can see that there's this class called
GenerateTokenRequestV2Dataset. The name incompletely sucks,
we're sorry about that. V2 datasets are not available
into V3 of the API, and in V2 of the API, there are no V2 datasets. As long as you can understand
that, you're fine. But the idea is that
we create these V2. The idea is that token
request, which are V2, support multi-resource, but the
ones that don't have V2 do not. But the idea is that now, what we're able to do, is we're able to create a
token request down here. Here is where we're
regenerating the token, there are the datasets,
there are the reports. Also, if I want to
create a new report, you need to have the resource
of the Target Workspace. But the idea is that now, I can just basically create
a single Embed Token. If we go back over here. Here's where the demo
was ending, I promise. Now, let's go ahead and
bring that back over here. Now, we're going to start
looking at things inside. Once again, as we look at that
particular ViewModel inside here, we basically have one token that we're using
for every single report. Once again, it's just saves
you from calling across the network and just gives
you a much better way to have a very performance application
with Power BI embedding. >> Awesome. >> Okay, so what's our
call to action, Kelly? >> What? We've got a
Call to Action Temp. >> That is so. As far
as the call to actions, I'd say I want every one of you who is willing to go
through that tutorial. Also if you want to enter the
camper competition, please do. I'd love to see lots
of different entries. I'd love to come back next
month and tell you we have 10 great three-minute
videos to show you, of people that took
this idea and went further with it and
then also come back next month because
we're going to have our second session on PowerShell. With that, I'm all done and I think we have at
least 75 seconds left, so Kelly, should I come back to you? >> Thank you so much. We've got
about three or four minutes. We've got a couple of
questions if that's okay. Love the session,
super-excited about doing all of these activities. First question, does someone
know if we can develop an MVP app with Power
BI but without Azure? >> There's no reason to have Azure. I think what you probably mean is the Azure embedding
service for Power BI. But the example that I just showed, there's no Azure involved as you're
doing your development work. We're just using Power BI Pro accounts because it's
User Owns Data embedding. Now, if you want to do App Owns Data, then you're going to have to
get a dedicated capacity. Lots of people will go to Azure and create instances of the
Power BI Embedded service. >> Does the Row-Level Security
work with the first version? >> Well, I'm not exactly sure what
you mean by the first version, but Row-Level Security works with every form of
Power BI embedding. >> Thank you. >> If you're using User
Owns Data embedding, the user identity flows through
and Row-Level Security on an embedded report works
just like it did if that same user went to
the Power BI service. Now with App Owns Data, because the user identity
isn't propagated, you have to use something
called the effective identity. When you create an embed token, you basically embed the
effective identity of the user, which includes the username and
whatever roles the user is in. But you can actually use Power BI Row-Level Security with everything we've
talked about today. >> Awesome. Can this talk apply to Power BI Report Server
versus online Power BI? >> Yes. Unfortunately, nothing we talked about today will work
with Power BI Report Server. Power BI Report Server has a completely different
set of APIs that are carried over from SQL
Server Reporting Services. Unfortunately, everything
we've talked about is a Cloud-only undertaking. >> I did this with my pro account. What are the limitations
of this approach versus the premium license
to embed the reports? >> If you're using User Owns Data, there are no limitations. It only gets to be if you're doing App Owns Data and you
get embed tokens. If you don't have a
dedicated capacity, there's a finite number of embed tokens they will give you
for doing things like prototyping. But once that number runs out, you're going to have to basically
run your content out of a dedicated capacity for it to work. >> Excellent. With MVC and
Power BI or SharePoint, can I do an editable table and being inserted onto
the SharePoint list? >> Not in Power BI. Nothing there relates to
Power BI development. You could create an application with.NET Core that did
something like that. But we won't use any of
the APIs we talked about, we probably use the
Microsoft Graph API to create some user
interface into SharePoint. >> If the API is not updated or
cannot be for whatever reason, is it safe to pull back
onto the raw HTTP calls? >> Yes, absolutely. I mean, if you want to call to
the.NET Service API yourself, there's nothing stopping
you from doing that, someone might say you're crazy. It's like hitting
yourself on the head with a hammer because it
feels so good when you stop. But if you move over to
another platform like Java, there is no SDK, so you have to make the raw calls. There have definitely been times over the last four years where the SDK doesn't cover something that I
know is in the underlying API. We'll pull out HTTP client and
we'll just do raw rest requests and have to deal with the access
token because not as pretty, but it has the exact same result and sometimes it's necessary,
so great question. >> What is the cost of ignoring
the token [inaudible] , asking for a new token
before each API call? >> Well, the cost of ignoring token [inaudible] is just more round trips. If you had an application
with 100 users, you might not ever notice it. As you start scaling
higher and higher, if you have a request that is making 10 different
calls to Azure AD, each time a page is loaded, so you basically get the same
app only access token 10 times, it's going to hurt your scalability. But when you code and you
have scalability issues, if your user base is small enough, it might never show up. I'm a big fan of not optimizing
until it's necessary. But that's the issue, it's round trips and making
your code more scalable. >> For an app as data
owner implementation, what Power BI license is required? >> For App As Owner, generally you'll need
of Power BI Pro license just to use the Power BI
service and do things. But with the Power BI Pro license, if you're not in a dedicated
capacity, once again, there's a finite number of embed tokens that Microsoft will pass back to you before
it turns it off. The number's around five or 10,000. It's not a documented number. But after that, you have to
get a dedicated capacity. You can get an A1 in Azure, which starts out a dollar an hour. It's a fairly low entry point. But what people find
is that can I use the free embed tokens for a prototype or for a certain
amount of development? It might be one week
for one developer and six weeks for another developer. But at some point if you're
doing serious development, you also have to do
your development on top of SKUs as well for
dedicated capacities. >> There's a couple
of related questions. Can the custom reports be user
specific with app owned data setup, and are there any security
concerns with the token being on the client as text? >> As far as can customer reports be user-specific with
App Owns Data, no. There's a lot of things that
Microsoft is coming out with personalized visuals and being able
to remember a filter settings. That's only going to be supported
for User Owns Data embedding. But unfortunately,
there's no plans to try and support that
with App Owns Data. Are there any security
concerns with the token being on the client as text? If you're using User Owns Data, you are only putting the Azure AD access token on the desktop of the user that
knew the password to get it. So that's not considered
a big violation. If you are doing App Owns Data
and then you take a master user, Azure access token and
you pass that back, that would be a big problem. With App Owns Data, you have to work with
embed tokens and Azure AD access token
for someone that had admin privileges on
multiple workspaces, that would be a huge security
risk to pass that back to the desktop of 1000 different
users, so we don't do that. Hopefully, that
answered your question? >> I'm not sure it's AJ's
question was completely answered. It's token resource on multisource. Does it use to get access to all
the reports in the workspaces? I think you did partially
answered that before. >> For AJ's question, does the user get access to all
reports in the workspace? If your code wants them to. The idea is that you
can see every report and every dataset
and every workspace, and so when you build
the embed token, you can put whatever resources
you want inside of it. You could have a custom application where a workspace has 10 reports, but you only gave a certain user
access to five of those reports. Once again, what you put
as far as resources in the embed token is your security. Generally, we don't like to
do security by hiding a link. We want security inside
the embed token. Whatever resources you embed the user can see with
that embed token, whatever resources you leave out are secured from that user
being able to access them. That's great question, AJ. >> Then last question, is there a Java
tutorial for Power BI? >> Is there a Java tutorial? No, there is not. I spent a lot of time
with Java in 1997, but I gave up Java when.NET Core
came out in preview in like 1998, and I haven't done
much work with that. Certainly, our team
is working to build resources for people using Java, trying to create SDKs and
the libraries that help. But I don't foresee
we'd have this type of a tutorial in the near future. So I apologize for that. >> I think that's all
for the questions. Thank you so much, Ted. This was fantastic. I really encourage
everybody else to go and complete the activities. Ted, final words from you? >> Yes, let's have everyone go
out and complete that tutorial. Other than that,
thank you campers for spending an hour with
us and hope to see you next month when we drill into PowerShell for Power BI. Thanks everybody.