Login Form Error Handling - A TimCo Retail Manager Video

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to our video in the tIMCO retail manager course this course focuses on real-world application development right now we're working on building our first section of work which is a basic register in this video where I continue working on our login form now if you're a patreon supporter at the $5 per month level or higher make sure you head over to the site to get the latest source code either way make sure you subscribe to this channel so you can follow along finally as you think of suggestions please leave them in the comments below I want to hear your thoughts in this course I've got a running list of suggestions for improvements and they'll definitely make this application better so let's get started now the first thing I usually forget to do this because just kind of have it when I'm working by myself not to do it and that's a kind of bad habit I'm gonna go to teen Explorer and go to sync and just hit fetch and make sure there's no remote changes on a server that I don't have and there's not because I'm working a teen environment of one now occasionally there will be some in here because I changed something on the server on Azure DevOps itself which create a commit but I haven't done that so let's go to a solution Explorer and let's look at the desktop UI where I look at the view and view model for the login view where we left off is we wired up this login button so that they put the username and password in hit login it comes down here to this login method which is asynchronous and the reasons a cigarettes is because it's calling an API we want make us those calls asynchronous not synchronous that way doesn't lock our application up and by default API calls are web called in general are asynchronous so we're going to wait that result and based on that result we're doing nothing right now we're just saying yeah we got it now that returns a authenticated user model so as this right here which is an access token and a use so that's what returns and we're just capturing it now if it fails we just temporary play console.writeline they're essentially just we have something in there to show that we can put a breakpoint on essentially and then read this exception so that's really all there was to it so we need to get rid of this and actually do something here and then we're going to talk about what we're gonna do for this returning result we're actually got the information now what okay so let's start with a catch what do you want to do when it fails when the the login name or password is incorrect when the API couldn't be found all these different type of things what should we do I think the best thing is simplest in it that's well like the keys here you go crazy with you know being really in depth in your error messaging and how you display that the user but I think the basics here are right above user name and the text box I want to put a red text that just gives the the error message essentially so let's do that and how we do that because that sounds great but but yeah how do you do it well we're gonna do is right now we are on row number one it looks like so it's Row one and login form as in row 0 well we're actually going to add a new row around bumping down so let's start up bottom up and say this is Row 4 then this is Row 3 and so is this oops that's three not not five three there we go and then we have this is Row two and Row two so list mostess thanks that for our login box which got quite large and that's because we're on row four which zero one two three four is the one that is the the auto height tips there we go four is the auto height row I'm sorry the star height which is it automatic resizes two divers left so let's copy one auto row and paste it down below and now I have an extra row that's below the login that actually has the extra information or extra space so now we have row number one is not currently being used so we can edit and this is the the error message row so let's put text block or you have a name because we're actually going to modify it so it's good that a name let's call it the no let's go simple go error message and we're gonna say for right now let's give it a text we read eliminate this in just a minute this is just for testing purposes this is a an error message something like that and then we need to give it a grid dot row is Row one and grid column is column one we want to call them span a to grid column span two columns and let's see how it looks like so so that's that's what our our message looks like my cursor down here there we go not great so if I want to give it some more space and let's what a color the color right now is black not a big fan of that amount red so let's give it some space first right now that margins let's get a margin below so margin let's give it zero zero a twenty zero long one there we go twenty get twenty underneath and we rank you've a color of red there we go so now that looks a little more important now if we make it larger that message let's just see that looks like so that makes it larger but it's not great it kind of expands out too far it makes you know everything look a little ugly so let's give it a max width so right now we have and let's let's cut this out for a minute here's a trick so right now it tells me what my column widths are okay so setup here is just one thirty four and it says 172 add those together I have three hundred and six so that could be my max width is three hundred and six let's put it three hundred instead so max width is three hundred so now if I paste that back in notice it doesn't actually go outside the box it stays into the box but it it doesn't wrap so let's let's fix that so let's go back up here to our error message let's come down the next line let's say text wrapping equals wrap and there we go so now was doing is gonna wrap down to the next line the next line until it fills up the space that it needs this is the the beauty of de PF is it will fill the space that it needs and it will contract away when it doesn't need that space anymore so this looks good right here I think I like it so we're going to do is we're going to wipe out this text property because this was just for testing the actual test the actual value comes from the the view model but here's a problem because I set the margin to be the bottom of 20 it's keeping that space even when nothing is there so we really wanna get rid of the margin so don't have that available anymore so that still isn't right and the reason why is because this is still visible and so it takes up one character height even those no characters in the text box however there's a visibility property if we set that the collapse notice how it collapses over here we can't see that space let's just put back in place the margin so zero zero zero and 20 and notice nothing changes over here but if I take away my visibility collapsed it brings back the whole box and the margin so that's what I need to do you know apply a visibility to this box how do we do that well we're gonna have to use some custom binding so I say visibility again equals binding on you know how property yet so let's just say we're gonna name it is Error visible it's a boolean variable and we make converter does it not kind of scroll a bit so I'm going to put this one I've scroll because I can't really help it converter equals not a curly brace static resource boolean to visibility converter curly brace okay now it gives us an invalid markup but don't worry we'll take care of that firstly make sure you have the right number of curly braces and we do not there we go now you have the correct number of curly braces because we have one here so it's two here now that remove one of those got the other side right there and then we had a last one right here remove that one you're good to go so two opens two closes that's good so what we doing well we're using a binding here that is inside caliber and micro actually it's not caliber and micro it's built into a PF sorry so it's still young at those alias though I'm saying I can't find the resource boolean divisibility converter so what we do well when you actually put that resource in the system now it's actually I said built-in so he's go to app sam'l and here we have our resource dictionary which we're merging in bootstrapper but below the merged in dictionary dictionary from bootstrap we want to bring in our boolean to visibility converter that's we're looking for now if you got to give an a key the key is how we refer to it now what I'm going to do is give the same key as the name itself that is keep it simple and you're not wondering you know where that come from how we do that it's you know it's a one-to-one relationship which that's what I used over here where I said static resource from the resource dictionary I want the boolean to visibility converter so what does this do what converts a boolean which returns true or false to visibility because visibility doesn't have true or false it has visible collapsed and hidden there's three different states and there none of them are true or false so what does it says if it's true then it's visible if it's false it's collapsed we don't deal with hidden okay so we're gonna do collapsed or visible and that's based upon the binding for is error visible so let's add the is error visible and error message properties to our view model let's go out a few model and we need a couple of properties here so let's create our construct or our property so propyl and we're going to say this is a sorry boolean and we called it is error visible so I'm going to call it underscore lowercase I is error visible and then is error visible just like a called a for and there's our boolean now we can change this set to have a notify of property change let's grab a copy of this so know if I have property change for is Error visible all right and now we need one more and this is for the error message let's copy that I will do our prop full this is a string and this is underscore error message error message and again we're going to change this to have a notify of property change and this is going before the error message but we should also have one for is visible because the visibility will change as well and actually I'm gonna make that's a read-only property because there's no reason for us to have a backing field even for this for is visible because this is just a calculation so let's do this so instead of returning this we're gonna return you to it in line or we can do it in a series of lines let's let's do a pool output equals false and then say if error message dot length is greater than zero that's greater than zero output equals true and then we return output which I have to return sickness now there we go so that's our is error visible it's just a get into the calculation but we still trigger the notify property change whenever the error message changes so let's see if this works all you do is come down here where it has an exception and say error message equals a X dot message and that should be all we need to do is begin error it's going to play into the error message property which is going to trigger the notify of property change let's see if it works now remember playing running this is going to start two things one is gonna start our web server and that's right there and so it's loading up to make sure the API goes get started and we can use it from our data PF application it'll also start our DPF applications so that we can actually log in unfortunately it hangs up right here we like to visual studio we find out why we're saying if error message length is greater than 0 but it's null so we need to fix that the quickest fix is that right there put a question mark after error message if it's null it's not going to be have a length of greater than 0 therefore it's gonna skip this whole thing I'll start again now that's running and our de PF applications right where it's waiting for there we go our API start now let's type in test test and hit login which that should not work because test test is not a valid username password and we hit login and we get bad request and it's in red excellent so now if I were to say Tim I am Tim Cory calm and PWD 1 2 3 4 5 . and hit login that should log in in fact let's let's verify that does I put in a breakpoint at our at the end of our try so let's go back over here and hit login and in fact it does login and the result says here's a token and here's a username so it worked now the the other knob but somebody haven't handled yet is the fact that it still says bad requests right here now this will go away because where I closed a login form but it's not good form to have the the bad requests stay there so let's go ahead and take care of getting rid of that error message once we retry to login all right so let's stop this whole thing so if we get an error message we put or if we catch and exceptionally put the error message into the display box but if we don't get an error message or when we're trying actually so we first try something we should say error message equals empty string that way we reset that box every single time that clears out our error now we also talked about last time the idea of making these boxes bigger because are too small right now and right now the again that column width is a hundred and seventy two so let's change these boxes instead I'm them width of a hundred and fifty let's make them at least let's go three fifteen see what that looks like that seems more like what we've been seeing when I actually fill in my my login and password now notice that if it's hard to see but there you go it actually resized both of these not just one even though the other one says minimum width of a hundred and fifty that's because with a beauty of DPF this column that they're in is Auto resizing it resizes to the largest element and everything else will just fill the space unless you give it an actual width which we're avoiding we don't want to give it actual widths and Heights so this one's 350 therefore this one matches even though the minimum is 150 as the minimum it's not the maximum so we can change it to match just we have the two in sync and now we're set user name is is right next to in password there right next to the boxes so if you notice that's there's not a lot of space between these two things so let's give it a little bit of margin so let's go over here it is the right margin so it's actually this one right here and that's just keep it v and we'll do the same thing for the password box so v and now if we look at this we see it's a little more space between the username and the textbox in the past or in the text box as well so because it's a little more space here also notice that this is taking up space in development mode even though it's not in production mode and that might be bothersome because the form doesn't look like this normally it only looks like this was an error and there's actually text here so how we get design time support for no space here well we can come up here to our binding this is this visibility right here now this is very long already but we can put after our converter we can put comma and say fallback value equals collapsed and what that will do notice it took it away is it says if you can't find a value like if that if that boolean wasn't there that that error message property wasn't there then I'm sorry he's visible error visible property so that binding wasn't there it's gonna fall back to collapsed which is fine because if it's not there got a problem and we wanna show an error of nothing because it's not there so therefore we want to be collapsed by default and also that effects design time so now by default since there is no property backing a design time it falls back to the fallback value which is collapsed so now I have this message it's working a little better I think let's let's start up and make sure that we have something you know more more useful or at least more pretty so let's start off with our test test notice the extra space we hit login and it's taking a little bit too run that's why it popped up again and it's going away right away that's not what we're looking for so something is happening that we're not anticipating so let's step through the code and find out why it's setting it from one value to the other so let's start with our our error message here I have a feeling it might have something to do with the fact that this is asynchronous and maybe we have an issue where it's hit an exception doing this message and then coming back and saying this which which seems odd but let's let's try and figure it out now one thing I note when you're doing asynchronous calls you're stepping through which you can do it changes the timing so the fact I'm gonna step through this may make it work and that's okay it's a little frustrating but it's okay just know that probably the reason that it is timing because you change the timing when you run it yourself I mean this thing's been chugging along and I've had you know hoping for a little bit so if I pause it and talk to you what's gonna take a few seconds in fact this is you know this is where it's paused it's taking a few seconds it might be that I fixed the time you sure already we'll see so we're going to go to step into which is f11 I'm going to step into this one again and it's gonna go to the API help us step let's actually step out of this one I don't want that the error message right now is empty string it's already calm come to the exception which exceptions not loaded yeah let's load that there you go now the exception is lo it we have a bad request there's our bad request right there there's no inter exception and now let's set the error message to e^x dot message and we'll we'll step into this call an error message is still bad request then it should be that it displays in the form but it's not right now so we're not quite sure why that currently isn't set let's hit pause right now we're going to do is look at let's see if we can't find someone we can look at this this property which the problem with a view model is we're not actually pause on our view model or pause on our view so we can't notice I'll you have access to our view model directly but we can do is we can take a look and debug a different way so debugging it's hard and it leads to blind alleys and dead ends and it can get frustrating at times the thing is just keep poking at it that's my philosophy at least when I can't figure something out I just keep coming in from different angles now the other thing is I haven't changed much which means it's not hard for me to undo everything I just did and try it again and make sure it works so right now I did put this question mark in here so maybe that's causing an issue but I don't think that it worked before it now I think about it worked when it first started I first tried this that question mark is already in working but down here let's look at our login I did change this so let's comment that out we haven't seen that yeah therefore it's one of my changes so let's just comment just that out and see if it solves our problem for us so as your API it's running test test hit login there we go now it seemed like the first time hit login nothing happened the second time something happened so I'm thinking it's not actually triggering the the the redisplay on this page I think that's what's happening so now I've got kind of clue so let's do this let's stop this or I start it again and I'm gonna put a breakpoint right let's say not line 94 because you'll always come to line 94 my hit login 1 if this starts mess a test test and hit login and so it went there now let's step over this it goes right to the exception error message currently is null and if I step over this error message is now bad request I hit continue there's no message on the display I can type other things in here nothing but if I hit login again it goes back here again error message already has bad requests in it but if I hit that exception again and hit continue now it says bad request so what's the issue here I think the issue is we're not capturing that the let's go let's go look at it we're not capturing the notify of property change for error message or is error visible one of two probably is error visible now I've got a theory here and it's a wacky theory they may be wrong but is error visible only has a gift it's read-only what if this system doesn't like that I'm gonna put a set there just to see what happens and then I will I've proven that this isn't really the issue the error message equals empty strength still I keep it commented for now but that shouldn't be the issue because that wasn't we know that somebody else was causing the error I'm not saying that wasn't didn't contribute oh test test hit login nothing happened so that wasn't it it's always good to try stuff though okay so it wasn't a set that was the problem I'll take it back out I don't want to have too many changes floating around and sometimes when you're looking at code you stare at something and maybe you've been stared this Korean yelling at me the whole time good for you you got it before I did but sometimes you stare at your code and may walk away for a little bit I didn't but I did pause the video for a second and just kind of took a deep breath and I figured you didn't didn't need to hear that but I found the problem please I'm pretty sure II found a problem error message we have a get that returns the error message we have a set that notifies a property change for is error visible and error message and then it sets the error message so what happens the first time we change our error message to have a full-strength something other than empty string well before we change the value away from null or empty string we tell everybody it's been changed and so if the timing is right and it evidently is we're gonna have the page refresh that value the form and then it will show the error message or up to the air message property but it's too late because it's already updated and that's waiting for the next update so it's an ordering thing change the value first then let people know don't let people know and then change the value they're not waiting and watching now this way they are observing what has been done in the new state not waiting for the change you're about to make so that was my bad let's put this back in as well let's run this and see if it doesn't fix our problem all right so we have a login test test login bad request excellent Tim Tim Cory I come PWD 1 2 3 4 5 . login that clears the screen now if I were it an extra M there hit login I get a bad request I take it away actually if I hit K there I hit login it's gonna go away for a second and come back but now if I hit login we're good to go so it's working the way we expect it to so now it's clear in the error message out when we no longer have an error or we're trying over and we get an error it puts that into the message box now at this point we're gonna stop because I think it's a good a good stopping point to be at we've got the login form fully working so that if it's yeah authenticates great it has the information back if it doesn't authenticate for ever reason we get a message back saying hey is that a bad request Lea display that's the user so we're all set now for the next step the next step is kind of a a cross-cutting step what I mean by that is we're gonna have to do a little bit of work in the let's look at the solution Explorer it's a little more obvious so we're going to do a little work in our API where I grab this information let's pull it up the user information where I grab the first name the last name the email address and we'll pull the date create I'm not sure round need it but we'll pull it so we have it so we grab all the information from the database through the API and into our login page where we're going to load it into a a singleton object they'll store that fill a lifespan of that logged in user so as long as the users logged in will have what their first name and last name are what their email address is will have that ID of theirs so we can use that for all future calls and we'll know when they were the account was created for them so I'm going to do this hopefully an all-in-one video because that way it gives you a full start to finish going from the database probably a store procedure for that for the pull of the information and then the API creating the endpoint for getting that information based upon again who's logged in and then this you know pulling that through to the front-end and putting it into a singleton we can then use for the rest of that users lifespan and it will go ahead and destroy that or reset that singleton when they log out so that's the next video but for now thanks for watching as always I am Tim quarry you [Music]
Info
Channel: IAmTimCorey
Views: 20,666
Rating: undefined out of 5
Keywords: .net, C#, Visual Studio, code, programming, tutorial, course, training, how to, tim corey, C# course, C# training, C# tutorial, C# app start to finish, timco, timco retail manager, wpf, asp.net, .net core, asp.net mvc, autofac, c# solid, c# solid principles, dependency injection, tdd, unit testing, xunit, moq, wpf resources, wpf resourcedictionary, c# api, c# api authentication, c# api authentication example, c# api authentication token, c# web api authentication
Id: LboWn0cEWBU
Channel Id: undefined
Length: 37min 29sec (2249 seconds)
Published: Mon Mar 11 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.