webForumDet fria alternativet

errorhantering

11 svar · 715 visningar · startad av doggelito

doggelitoMedlem sedan juni 20003 076 inlägg
#1

Måste implementera lite errorhantering till mitt projekt och har nu ett par funderingar.

Ex.
Jag har en metod som byter namn på en mapp.
Men om användren t.ex försöker byta namnet till en tom sträng så ska ett fel visas som säger typ att mappen måste bestå av minst ett tecken, hur löser ni det?

Har en aspx som visar mappen och möjligheten att byta namn samt ett BLL där metoden ligger.
Metoden är inte klar men kommer väl att se ut typ:

        public bool RenameFolder(string NewName, string FolderPath)
        {
          
            DirectoryInfo di = new DirectoryInfo(FolderPath);
            
            if (NewName.Length == 0)
                //kasta ett error till användaren att mappen måte bestå av minst ett tecken
            ...
            di.MoveTo(Path.Combine(di.Parent.FullName, NewName));
            //Kasta tillbaka "success! mappen ändrad"
            return true;
            ...
         }

Hur returnerar man fel till aspx sidan från BLL:n?

Har googlat en del men inte hittat nån bra sida som tar upp error/infohantering till användaren, alla sidor handlar bara om de inbyggda exeptions som genereras vid fel.
Nån som vet en bra sida som tar upp egna specifika errormeddelanden?

GladhMedlem sedan maj 20012 812 inlägg
#2

Generellt så skall du endast använda dig av exceptions när något oväntat inträffar. Att en användare skriver in en tomsträng är något som du kan förvänta dig och du bör därför inte kasta en exceptions för detta, utan bara returnera false, med meddelandet "Namnet måste innehålla minst en bokstav".
Anledningen till detta är att det är väldigt kostsamt att kasta en exceptions och alltså något som man vill undvika i prestandakrävande kod. Nu är det dock ett perfekt sätt att berätta för användaren om vad man kan kalla "bussiness-fel", vilket gör att man använder det ändå, men som sagt, tänk dig för om det är en komponent som du gör som skall användas av många samtidiga användare, att då lösa något "förväntat" fel med excceptions kommer ge dig prestanda problem.

För övrigt så har jag det så att jag har skapat en egen BaseException-klass som innehåller lite variabler, sedan har jag skapat 2 exceptionsklasser som ärver av min bas. Dessa heter Technical och Business. Sedan skapar jag nya exceptions utifrån dessa 2 som basklasser, och då kan jag sedan urskilja om det felet som jag får tillbaka är tekniskt eller affärsmässigt, och om det är affärsmässigt så kan jag visa mer information om felet än om det är tekniskt (jag skulle ju aldrig vilja visa en connectionstring till databasen ut till användaren).

- M

doggelitoMedlem sedan juni 20003 076 inlägg
#3

Ok, intressant!
Om man får fråga, hur löser du infotexter på för sett?
Som i mitt exempel:
Användaren byter namn på en mapp och får texten: "Namnet på mappen bytt" i en label eller liknande.

Ska jag ändra min metod så att den returnerar en sting istället för en bool och där i returnera texten till labeln?
Problemet då är ju att man inte kan särskilja på samma sätt om namnbytet lyckades eller ej!

GladhMedlem sedan maj 20012 812 inlägg
#4

doggelito skrev:

Ok, intressant!
Om man får fråga, hur löser du infotexter på för sett?

Du returnerar varken string eller bool, utan en class/strukt med en bool och en string, som då kan hålla både text och värdet om det gått bra eller ej.

- M

doggelitoMedlem sedan juni 20003 076 inlägg
#5

Jag tror ta mej fasen att jag fått till det! Trots min bristande kunskap inom OOP :)

Jag skulle uppskatta dock om nån bara ville ta en snabbtitt på denna kod och kommentera ev. "newbe"-misstag som man bittert får ångra sedan! :stud

hanterar svar till användaren

    public class MessagesBLL
    {
        private bool _result;
        public bool Result
        {
            get
            {
                return _result;
            }
            set
           {
                _result = value;
            }
        }

        private string _message;
        public string Message
        {
            get
            {
                return _message;
            }
            set
            {
                _message = value;
            }
        }

        private MessagesBLL()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        public MessagesBLL(bool result, string message)
        {
            Result = result;
            Message = message;
        }

    }

byter namn på en mapp

        public MessagesBLL RenameFolder(string NewName, string FolderPath)
        {
            DirectoryInfo di = new DirectoryInfo(FolderPath);

            //namnet för kort
            if (NewName.Length == 0)
                return new MessagesBLL(false, "Namnet måste vara minst ett tecken.");

            //mappen har samma namn
            if (di.FullName.Equals(Path.Combine(di.Parent.FullName, NewName)))
                return new MessagesBLL(false, "Namnet är samma som ursprunget.");

            //byter namn om det inte redan finns en mapp med samma namn
            if (new DirectoryInfo(Path.Combine(di.Parent.FullName, NewName)).Exists)
                return new MessagesBLL(false, "Det finns redan en mapp med det namnet.");
            else
            {
                di.MoveTo(Path.Combine(di.Parent.FullName, NewName));
                return new MessagesBLL(true, "Namnet på mappen bytt.");
            }
        }

användaren byter namn på mappen från websidan

            MessagesBLL messages;
            messages = RenameFolder("blabla", "d:\bla\bla");
            bool _result = messages.Result;
            string _message = messages.Message;
            Response.Write(_message);
GladhMedlem sedan maj 20012 812 inlägg
#6

Det ser bra ut. (y)

Och nu när du vet hur du skall göra och varför så får du lova att använda dig av Exceptions ;)

Att använda sig av Exceptions är helt outstanding i vissa tillfällen (även om det inte skall användas då) så om man bara är medveten om vilka nackdelare det ger (prestanda) så får man lov att bryta mot gängse standard.

Lycka till med felhanteringen...

- M

doggelitoMedlem sedan juni 20003 076 inlägg
#7

Många tack Gladh! :bire

DinoMedlem sedan sep. 20011 914 inlägg
#8

Tycker inte det är något vidare vackert. Förstår inte vad meddelande texten har i den metoden att göra.

Skulle gjort så här:

public enum FolderStatus : int
{
   LengthIssues,
   FolderAlreadyExists,
   DublicatedFolderName,
   Success
}

public static class Utility
{
   public static FolderStatus RenameFolder(string NewName, string FolderPath)
   {
      //namnet för kort
      if (String.IsNullOrEmpty(NewName))
         return FolderStatus.LengthIssues;

      DirectoryInfo di = new DirectoryInfo(FolderPath);

      //mappen har samma namn
      if (di.FullName.Equals(Path.Combine(di.Parent.FullName, NewName)))
         return FolderStatus.FolderAlreadyExists;

      //byter namn om det inte redan finns en mapp med samma namn
      if (new DirectoryInfo(Path.Combine(di.Parent.FullName, NewName)).Exists)
         return FolderStatus.DublicatedFolderName;

      di.MoveTo(Path.Combine(di.Parent.FullName, NewName));
      return FolderStatus.Success;
   }
}

class minsida_aspx : Page
{
   public void Page_Load(object sender, EventArgs e)
   {

   }

   protected void btChangeFolderName_Click(object sender, EventArgs e)
   {
      string message = String.Empty;
      FolderStatus fs = Utility.RenameFolder(tbNewName, tbFolderPath);
      switch(fs)
      {
         case FolderStatus.LengthIssues :
            message = "Namnet måste vara minst ett tecken.";
            break;
         case FolderStatus.FolderAlreadyExists:
            message = "Namnet är samma som ursprunget.";
            break;
         case FolderStatus.DublicatedFolderName:
            message = "Det finns redan en mapp med det namnet.";
            break;
         case FolderStatus.Success:
            message = "Namnet på mappen bytt.";
            break;
      }
      Response.Write(message);
   }
}
doggelitoMedlem sedan juni 20003 076 inlägg
#9

Ja, det ser ju onekligen vackrare ut! :)

Du säger "skulle gjort så här", hur gör du själv och även du Gladh, hur gör ni kortfattat när ni visar meddelanden till användaren?
Har ni en liknande uppbyggnad av klasser?

Jag söker å söker på nätet men ingenstans finns nått exempel på hur man hanterar meddelanden till användaren i olika scenarion, är det ingen som berättar för användaren vad som försigår i koden eller? :q

DinoMedlem sedan sep. 20011 914 inlägg
#10

Gladh skrev:

Generellt så skall du endast använda dig av exceptions när något oväntat inträffar. Att en användare skriver in en tomsträng är något som du kan förvänta dig och du bör därför inte kasta en exceptions för detta, utan bara returnera false...

Alltså ett exception är något som applikationen skall hantera och för programmeraren att lösa. Besökaren skall aldrig ta del av dessa utan helt enkelt skickas till en felsida när ett sker.

Mer läsning

Min valideringsmodell av användardata sker ungefär som i koden jag gav.

emissionMedlem sedan dec. 19996 721 inlägg
#11

Kärnan ligger lite i att göra sig bekväm med ordet Exception. Exception betyder inte fel, utan undantag. Vissa mer troliga andra, men sensmoralen bör vara att om man kan förutsäga och fånga felet själv så ska man göra det.

GladhMedlem sedan maj 20012 812 inlägg
#12

Dino skrev:

Alltså ett exception är något som applikationen skall hantera och för programmeraren att lösa. Besökaren skall aldrig ta del av dessa utan helt enkelt skickas till en felsida när ett sker.

Det där vet jag inte om jag håller med om. Det finns så många olika typer av exceptions och precis som Emission säger så är ett exception ett undantag och inte ett fel, det betyder att exceptions används när något oväntat inträffar.

Visst finns det "Exceptions" som är möjliga att hanterar i sin kod, och låta flödet gå vidare bara med annan inriktning. Sedan finns det Exceptions som gör att du måste avbryta ditt flöde och presentera en felsida för användaren. Sedan så har du extrema exceptions som gör att du inte kan göra något annat än stänga ner din applikation, dessa fel kan du inte hanterar själv, utan måste bara döda applikationen, eftersom felet ligger på ett djupare plan än din applikation, minnesproblem exempel.

Men senmoralen är att visa saker som man kan förvänta sig och kontrollera själv innan skall inte lösas med Exceptions av prestandaskäl, utan lösas så som både du och jag föreslagit, andra fel som du inte kan kontrollera själv, typ nätverket dog, detta är ett typiskt exempel på där du har 2 möjligheter, antingen så lägger du en try-catch runt din "nätverks-operation" och löser problemet själv om det uppstår (om du kan göra det), eller så låter du felet bubbla upp till Applikation_onHandlingError och fångar det där och presenterar ett fel för användaren att operationen inte kunde utföras för att nätverket är nere.

doggelito skrev:

Du säger "skulle gjort så här", hur gör du själv och även du Gladh, hur gör ni kortfattat när ni visar meddelanden till användaren?
Har ni en liknande uppbyggnad av klasser?

Nope, jag skapar 2 typer av exceptions, technical och business. De problem som du får här skulle jag lösa genom att kasta ett businessexception och presentera meddelandet för användaren.

Och varför skulle jag göra så då? Helt enkelt för att det är enklaste och snabbaste sättet att lösa problemet med, visst är det fint med classer och enumerations som man skickar tillbaka när något fel inträffar, men det tar utvecklingstid att sitta och skriva alla dessa enumeration och klasser samt själv hanteringen av dessa när de returneras tillbaka. Och i vanliga windows applikationer så är inte ditt problem prestandan då dessa maskiner knappast är belastade till max.

Så jag skulle helt enkelt skapa en FileErrorExceptions som ärver från min BusinessExceptions och kasta detta fel med ett meddelande att "Filnamnet var tomt, det måste innehålla minst 1 bokstav"...

Sedan skulle jag låta min generella felhanteringsmetod som ligger i Applikation_unhandlerError eventet hantera dessa fel och logga felet samt presenterar en information till användare om att ett fel inträffat, om felet är ett businessexceptions så visas meddelander, om det är ett technicalexceptions så visas ett standardmeddelande som säger att program har stött på ett tekninskt problem och man skall kontakta supporten och så skickas ett ID med som man kan ge till supporten så det kan slå upp felet i en databas.

Däremot om vi pratar centrala komponenter där prestandan är kritiskt så skulle jag inte kastat ett exception, utan loggat ner problemet till en log och sedan returnerat false, sedan är det upp till den applikation som kallat min komponent att hanterar om det kommer true/false tillbaka.

emisson skrev:

Vissa mer troliga andra, men sensmoralen bör vara att om man kan förutsäga och fånga felet själv så ska man göra det.

Jag skulle vilja lägga till inte bara förutse och fånga det, utan att du faktiskt gör något när du fångat felet. Att bara fånga felet och sedan kasta det vidare är det ingen som vinner på. Skall man fånga ett fel nere i sin kod, så gör man det för att man kan hanterar felet i sin kod.

- M

145 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
142 ms — hämta tråd, inlägg och bilagor (db)