Hi,
I have something like this:
try
{
// some code
}
catch // note - i am catching everything now
{
// do something
}
Will this sort of catch statement, catch 'unsafe' and 'kernal-level'
exceptions (even if the app is a simple asp.net app with no unsafe stuff)?
(just wanted to confirm as I had a debate with one of my friends - AFAIK i
feel it doesn't since no unsafe code is used and since Win32 exceptions are
mapped into managed .NET exception classes)
Also, in many cases, i have catch blocks which does nothing - because i
don't want any exception to be propagated...so mething like follows.
public bool IsInteger(strin g val)
{
bool result;
try
{
int.Parse(val);
result = true;
}
catch
{
result = false;
}
return result;
}
Is this OK (a good practice)?
Thanks,
Benny 13 3723
Benny,
If you use a catch, without specifying the exception, then that section
of code will be called whenever ANY managed exception is thrown in the try
block. Now, if there are SEH exceptions that are thrown that are not mapped
by the runtime, or somehow escape it, then the whole process is more than
likely going to come down, and it's a moot point anyways.
You also ask if the following is good practice: public bool IsInteger(strin g val) { bool result;
try { int.Parse(val); result = true; } catch { result = false; } return result; }
This is horrible. In reality, you should use the static TryParse method
to see if it can be parsed, or perform some parsing on your own. Relying on
any exception to be thrown is a poor indicator of what the problem really
is. You should, for example, catch ArgumentExcepti on (if the argument is
null, then it can't be an integer), and FormatException (the string is not
an integer) and possibly OverflowExcepti on (it is an integer, but can not be
stored in an Int32, how you handle this is up to you).
If you get an OutOfMemoryExce ption, then that has nothing to do with
your code, and you shouldn't just swallow it, as code up the stack might
need to know this is going on.
Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Benny" <Be***@discussi ons.microsoft.c om> wrote in message
news:F4******** *************** ***********@mic rosoft.com... Hi,
I have something like this:
try { // some code } catch // note - i am catching everything now { // do something }
Will this sort of catch statement, catch 'unsafe' and 'kernal-level' exceptions (even if the app is a simple asp.net app with no unsafe stuff)? (just wanted to confirm as I had a debate with one of my friends - AFAIK i feel it doesn't since no unsafe code is used and since Win32 exceptions are mapped into managed .NET exception classes)
Also, in many cases, i have catch blocks which does nothing - because i don't want any exception to be propagated...so mething like follows.
public bool IsInteger(strin g val) { bool result;
try { int.Parse(val); result = true; } catch { result = false; } return result; }
Is this OK (a good practice)?
Thanks, Benny
Hi Nicholas, If you use a catch, without specifying the exception, then that section of code will be called whenever ANY managed exception is thrown in the try
What is SEH?
Also, my question actually is - whether to add catch(Exception ex) to make
sure that it catches *only managed* exceptions. In other words, if I omit
(Exception ex), will the catch block catch unsafe and kernel level exceptions
too (even if there isn't any unsafe code directly)?
This is horrible. In reality, you should use the static TryParse method to see if it can be parsed, or perform some parsing on your own. Relying on
Only the Double structure has a TryParse method - an int doesn't (I am using
..NET 1.1) - were you referring to some other method?
My objective is to make sure that the utility method is fail-safe. In other
words, whatever error happens, the method must return a false. If everythings
fine, it must return a true. This is to ensure that the calling method need
not worry about exceptions - these are just utility classes.
Please share your thoughts.
Thanks,
Benny
Benny,
SEH is short for Structured Exception Handling, which is a way of
throwing/handling exceptions in unmanaged code. If the CLR picks up on
this, it is going to throw a managed exception with the details of the SEH.
"catch" will only catch managed exceptions. There is nothing else that
it can catch. If the CLR picks up on an unmanaged exception (that it knows
to look for), then it will wrap that in a managed exception and throw that.
If it escapes the CLR's watch, then the process is most likely coming down.
The only slight difference between catch and catch(Exception e) is that
with "catch" alone, you can catch anything, not just exceptions. You can
actually throw anything derived from object (i.e. anything) in managed C++,
but you can not do it in C#. With catch(Exception e), you will only catch
anything deriving from Exception (that isn't handled in previous catch
blocks).
The thing with catch (on it's own) is that you can't access anything on
the object that is thrown.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Benny" <Be***@discussi ons.microsoft.c om> wrote in message
news:E4******** *************** ***********@mic rosoft.com... Hi Nicholas,
If you use a catch, without specifying the exception, then that section of code will be called whenever ANY managed exception is thrown in the try
What is SEH? Also, my question actually is - whether to add catch(Exception ex) to make sure that it catches *only managed* exceptions. In other words, if I omit (Exception ex), will the catch block catch unsafe and kernel level exceptions too (even if there isn't any unsafe code directly)?
This is horrible. In reality, you should use the static TryParse method to see if it can be parsed, or perform some parsing on your own. Relying on
Only the Double structure has a TryParse method - an int doesn't (I am using .NET 1.1) - were you referring to some other method?
My objective is to make sure that the utility method is fail-safe. In other words, whatever error happens, the method must return a false. If everythings fine, it must return a true. This is to ensure that the calling method need not worry about exceptions - these are just utility classes.
Please share your thoughts.
Thanks, Benny
Hi,
The first portion is now entirely clear. Thanks.
However, could you please give ur opinion on the second section.
Copy-pasting for ur ref.: This is horrible. In reality, you should use the static TryParse method to see if it can be parsed, or perform some parsing on your own. Relying on Only the Double structure has a TryParse method - an int doesn't (I am using .NET 1.1) - were you referring to some other method?
My objective is to make sure that the utility method is fail-safe. In other words, whatever error happens, the method must return a false. If everythings fine, it must return a true. This is to ensure that the calling method need not worry about exceptions - these are just utility classes.
Thanks a lot!
Benny
"Nicholas Paldino [.NET/C# MVP]" wrote:
Benny,
SEH is short for Structured Exception Handling, which is a way of throwing/handling exceptions in unmanaged code. If the CLR picks up on this, it is going to throw a managed exception with the details of the SEH.
"catch" will only catch managed exceptions. There is nothing else that it can catch. If the CLR picks up on an unmanaged exception (that it knows to look for), then it will wrap that in a managed exception and throw that. If it escapes the CLR's watch, then the process is most likely coming down.
The only slight difference between catch and catch(Exception e) is that with "catch" alone, you can catch anything, not just exceptions. You can actually throw anything derived from object (i.e. anything) in managed C++, but you can not do it in C#. With catch(Exception e), you will only catch anything deriving from Exception (that isn't handled in previous catch blocks).
The thing with catch (on it's own) is that you can't access anything on the object that is thrown.
-- - Nicholas Paldino [.NET/C# MVP] - mv*@spam.guard. caspershouse.co m
"Benny" <Be***@discussi ons.microsoft.c om> wrote in message news:E4******** *************** ***********@mic rosoft.com... Hi Nicholas,
If you use a catch, without specifying the exception, then that section of code will be called whenever ANY managed exception is thrown in the try
What is SEH? Also, my question actually is - whether to add catch(Exception ex) to make sure that it catches *only managed* exceptions. In other words, if I omit (Exception ex), will the catch block catch unsafe and kernel level exceptions too (even if there isn't any unsafe code directly)?
This is horrible. In reality, you should use the static TryParse method to see if it can be parsed, or perform some parsing on your own. Relying on
Only the Double structure has a TryParse method - an int doesn't (I am using .NET 1.1) - were you referring to some other method?
My objective is to make sure that the utility method is fail-safe. In other words, whatever error happens, the method must return a false. If everythings fine, it must return a true. This is to ensure that the calling method need not worry about exceptions - these are just utility classes.
Please share your thoughts.
Thanks, Benny
As Nicholas pointed out, this is bad practice:
public bool IsInteger(strin g val)
{
bool result;
try
{
int.Parse(val);
result = true;
}
catch
{
result = false;
}
return result;
}
You should "never" have a catch-all like this: neither "catch" by
itself nor "catch (Exception ex)". You should, instead, catch specific
exceptions that indicate the problem you are looking for. As Nicholas
pointed out, in your case these would be ArgumentNullExc eption,
FormatException , and OverflowExcepti on.
* There is one case in which you have little choice but to "catch
(Exception ex)", and that is when calling methods written by third
parties, where the method documentation is incomplete and does not tell
you what exceptions the method can throw. For a good (?) example of
crap documentation, see the doc for the Crystal classes supplied with
..NET 1.1: the method parameter doc is barely adequate, and there is
_no_ mention of exceptions at all. In a situation like that, you can't
catch specific exceptions you don't know about, and you have to hold
your nose and "catch (Exception ex)".
Benny,
That is why I think you need to be EXTRA careful if they are utility
classes. You should not suck up exceptions that you have no intention of
sucking up, since they will just complicate your app later on.
If you are not using .NET 2.0, then you can use the Parse method on
Int32, and catch ^just^ the exceptions that I pointed out to you, since
those pertain to parsing the string, and nothing else. Then, in those
exception handlers, you can return false.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Benny" <Be***@discussi ons.microsoft.c om> wrote in message
news:28******** *************** ***********@mic rosoft.com... Hi,
The first portion is now entirely clear. Thanks.
However, could you please give ur opinion on the second section. Copy-pasting for ur ref.: This is horrible. In reality, you should use the static TryParse method to see if it can be parsed, or perform some parsing on your own. Relying on
Only the Double structure has a TryParse method - an int doesn't (I am using .NET 1.1) - were you referring to some other method?
My objective is to make sure that the utility method is fail-safe. In other words, whatever error happens, the method must return a false. If everythings fine, it must return a true. This is to ensure that the calling method need not worry about exceptions - these are just utility classes.
Thanks a lot!
Benny
"Nicholas Paldino [.NET/C# MVP]" wrote:
Benny,
SEH is short for Structured Exception Handling, which is a way of throwing/handling exceptions in unmanaged code. If the CLR picks up on this, it is going to throw a managed exception with the details of the SEH.
"catch" will only catch managed exceptions. There is nothing else that it can catch. If the CLR picks up on an unmanaged exception (that it knows to look for), then it will wrap that in a managed exception and throw that. If it escapes the CLR's watch, then the process is most likely coming down.
The only slight difference between catch and catch(Exception e) is that with "catch" alone, you can catch anything, not just exceptions. You can actually throw anything derived from object (i.e. anything) in managed C++, but you can not do it in C#. With catch(Exception e), you will only catch anything deriving from Exception (that isn't handled in previous catch blocks).
The thing with catch (on it's own) is that you can't access anything on the object that is thrown.
-- - Nicholas Paldino [.NET/C# MVP] - mv*@spam.guard. caspershouse.co m
"Benny" <Be***@discussi ons.microsoft.c om> wrote in message news:E4******** *************** ***********@mic rosoft.com... > Hi Nicholas, > >> If you use a catch, without specifying the exception, then that >> section >> of code will be called whenever ANY managed exception is thrown in the >> try > > What is SEH? > Also, my question actually is - whether to add catch(Exception ex) to > make > sure that it catches *only managed* exceptions. In other words, if I > omit > (Exception ex), will the catch block catch unsafe and kernel level > exceptions > too (even if there isn't any unsafe code directly)? > > >> This is horrible. In reality, you should use the static TryParse >> method >> to see if it can be parsed, or perform some parsing on your own. >> Relying >> on > > Only the Double structure has a TryParse method - an int doesn't (I am > using > .NET 1.1) - were you referring to some other method? > > My objective is to make sure that the utility method is fail-safe. In > other > words, whatever error happens, the method must return a false. If > everythings > fine, it must return a true. This is to ensure that the calling method > need > not worry about exceptions - these are just utility classes. > > Please share your thoughts. > > Thanks, > Benny >
> My objective is to make sure that the utility method is fail-safe. In other words, whatever error happens, the method must return a false. If everythings fine, it must return a true. This is to ensure that the calling method need not worry about exceptions - these are just utility classes.
Yes, but don't take "fail-safe" to extremes. If you catch an
OutOfMemoryExce ption, is your method really being "fail-safe", or are
you just swallowing an important exception and doing nothing with it? I
would say the latter. You haven't helped your caller out any by
throwing away a system-level exception like OutOfMemoryExce ption.
The general rule is simple: catch only exceptions with which you can
deal intelligently. There are only three situations in which I catch
exceptions:
1. When I want to transform the exception into a return value. For
example, in your case you want ArgumentNullExc eption, FormatException ,
and OverflowExcepti on to be transformed into a return of false,
indicating "this is not an integer." That's fair: each of those
exceptions is meaningful to you and your callers, it's just that you
want to change the way the caller receives that information: as a
return value rather than exception. OutOfMemoryExce ption, on the other
hand, does _not_ mean "this is not an integer." It means that something
went horribly wrong deep inside the .NET Framework, so it's not
appropriate to transform it into a return value.
2. When I want to transform the exception into a different exception,
because the low-level exception isn't meaningful from the point of view
of the caller. For example, I might want to transform a
DivideByZeroExc eption into an InvalidArgument Exception, because it's
more appropriate to tell my caller that they passed an invalid
argument; my caller doesn't care that I later used that argument in a
division operation. (Yes, I know, bad programming practice: better to
check for zero up front. :-)
3. When I know that I can recover from the specific situation that a
specific exception indicates. For example, I might get an exception
attempting to parse an XML file against a schema, but my application
can recover from that situation by running the XML through a transform
to bring it up to the latest version. In this case, I catch the
exception and then take a different path through my app. This includes
the case in which my application might want to ignore a particular
exception and keep going anyway.
The bottom line in all three cases is that I catch a specific exception
when I know that I can do something meaningful with that exception.
Never catch an exception if you then don't know what to do with it.
In the case of an OutOfMemoryExce ption, what is your method going to do
with it? Toss it away and keep going anyway? Is that a decision for
your method to make, or is that a higher-level decision for the calling
application? I would say the latter.
Hi Nicholas,
Thanks a lot!
I am now trying to unlearn this habit of mine and trying to think in ur
lines.
Thanks again!
Benny
"Nicholas Paldino [.NET/C# MVP]" wrote: Benny,
That is why I think you need to be EXTRA careful if they are utility classes. You should not suck up exceptions that you have no intention of sucking up, since they will just complicate your app later on.
If you are not using .NET 2.0, then you can use the Parse method on Int32, and catch ^just^ the exceptions that I pointed out to you, since those pertain to parsing the string, and nothing else. Then, in those exception handlers, you can return false.
-- - Nicholas Paldino [.NET/C# MVP] - mv*@spam.guard. caspershouse.co m
"Benny" <Be***@discussi ons.microsoft.c om> wrote in message news:28******** *************** ***********@mic rosoft.com... Hi,
The first portion is now entirely clear. Thanks.
However, could you please give ur opinion on the second section. Copy-pasting for ur ref.: This is horrible. In reality, you should use the static TryParse method to see if it can be parsed, or perform some parsing on your own. Relying on
Only the Double structure has a TryParse method - an int doesn't (I am using .NET 1.1) - were you referring to some other method?
My objective is to make sure that the utility method is fail-safe. In other words, whatever error happens, the method must return a false. If everythings fine, it must return a true. This is to ensure that the calling method need not worry about exceptions - these are just utility classes.
Thanks a lot!
Benny
"Nicholas Paldino [.NET/C# MVP]" wrote:
Benny,
SEH is short for Structured Exception Handling, which is a way of throwing/handling exceptions in unmanaged code. If the CLR picks up on this, it is going to throw a managed exception with the details of the SEH.
"catch" will only catch managed exceptions. There is nothing else that it can catch. If the CLR picks up on an unmanaged exception (that it knows to look for), then it will wrap that in a managed exception and throw that. If it escapes the CLR's watch, then the process is most likely coming down.
The only slight difference between catch and catch(Exception e) is that with "catch" alone, you can catch anything, not just exceptions. You can actually throw anything derived from object (i.e. anything) in managed C++, but you can not do it in C#. With catch(Exception e), you will only catch anything deriving from Exception (that isn't handled in previous catch blocks).
The thing with catch (on it's own) is that you can't access anything on the object that is thrown.
-- - Nicholas Paldino [.NET/C# MVP] - mv*@spam.guard. caspershouse.co m
"Benny" <Be***@discussi ons.microsoft.c om> wrote in message news:E4******** *************** ***********@mic rosoft.com... > Hi Nicholas, > >> If you use a catch, without specifying the exception, then that >> section >> of code will be called whenever ANY managed exception is thrown in the >> try > > What is SEH? > Also, my question actually is - whether to add catch(Exception ex) to > make > sure that it catches *only managed* exceptions. In other words, if I > omit > (Exception ex), will the catch block catch unsafe and kernel level > exceptions > too (even if there isn't any unsafe code directly)? > > >> This is horrible. In reality, you should use the static TryParse >> method >> to see if it can be parsed, or perform some parsing on your own. >> Relying >> on > > Only the Double structure has a TryParse method - an int doesn't (I am > using > .NET 1.1) - were you referring to some other method? > > My objective is to make sure that the utility method is fail-safe. In > other > words, whatever error happens, the method must return a false. If > everythings > fine, it must return a true. This is to ensure that the calling method > need > not worry about exceptions - these are just utility classes. > > Please share your thoughts. > > Thanks, > Benny >
Bruce,
It should be pointed out in #2 that the InnerException should be set on
such transforms.
"Bruce Wood" <br*******@cana da.com> wrote in message
news:11******** **************@ g47g2000cwa.goo glegroups.com.. . My objective is to make sure that the utility method is fail-safe. In other words, whatever error happens, the method must return a false. If everythings fine, it must return a true. This is to ensure that the calling method need not worry about exceptions - these are just utility classes.
Yes, but don't take "fail-safe" to extremes. If you catch an OutOfMemoryExce ption, is your method really being "fail-safe", or are you just swallowing an important exception and doing nothing with it? I would say the latter. You haven't helped your caller out any by throwing away a system-level exception like OutOfMemoryExce ption.
The general rule is simple: catch only exceptions with which you can deal intelligently. There are only three situations in which I catch exceptions:
1. When I want to transform the exception into a return value. For example, in your case you want ArgumentNullExc eption, FormatException , and OverflowExcepti on to be transformed into a return of false, indicating "this is not an integer." That's fair: each of those exceptions is meaningful to you and your callers, it's just that you want to change the way the caller receives that information: as a return value rather than exception. OutOfMemoryExce ption, on the other hand, does _not_ mean "this is not an integer." It means that something went horribly wrong deep inside the .NET Framework, so it's not appropriate to transform it into a return value.
2. When I want to transform the exception into a different exception, because the low-level exception isn't meaningful from the point of view of the caller. For example, I might want to transform a DivideByZeroExc eption into an InvalidArgument Exception, because it's more appropriate to tell my caller that they passed an invalid argument; my caller doesn't care that I later used that argument in a division operation. (Yes, I know, bad programming practice: better to check for zero up front. :-)
3. When I know that I can recover from the specific situation that a specific exception indicates. For example, I might get an exception attempting to parse an XML file against a schema, but my application can recover from that situation by running the XML through a transform to bring it up to the latest version. In this case, I catch the exception and then take a different path through my app. This includes the case in which my application might want to ignore a particular exception and keep going anyway.
The bottom line in all three cases is that I catch a specific exception when I know that I can do something meaningful with that exception. Never catch an exception if you then don't know what to do with it.
In the case of an OutOfMemoryExce ption, what is your method going to do with it? Toss it away and keep going anyway? Is that a decision for your method to make, or is that a higher-level decision for the calling application? I would say the latter. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Erlend Fuglum |
last post by:
Hi everyone,
I'm having some trouble sorting lists. I suspect this might have
something to do with locale settings and/or character
encoding/unicode.
Consider the following example, text containing norwegian special
characters æ, ø and å.
>>> liste =
|
by: KefX |
last post by:
This may have been discussed before, but I'm kind of confused as to why Python
doesn't support having both an except ~and~ a finally clause, like this:
try:
raise RuntimeException
except:
print "What is the answer?"
finally:
print 42
|
by: Robert Brewer |
last post by:
Alex Martelli wrote in another thread:
> One sign that somebody has moved from "Python newbie" to "good Python
> programmer" is exactly the moment they realize why it's wrong to code:
>
> try:
> x = could_raise_an_exception(23)
> process(x)
> except Exception, err:
> deal_with_exception(err)
|
by: David Stockwell |
last post by:
In referring to my copy of the python bible, it tells me I can't use all
three items 'try' except and finally. I can use the t/f or t/e
combinations though
What combination can i use if i want to catch the exception and still have a
finally block?
This is a fictional example of what I want....
|
by: djw |
last post by:
Hi, Folks-
I have a question regarding the "proper" use of try: finally:... Consider
some code like this:
d = Device.open()
try:
d.someMethodThatCanRaiseError(...)
if SomeCondition:
raise Error # Error is subclass of Exception
| |
by: William Park |
last post by:
(crossposted to comp.lang.python, because this may be of interest to
them.)
Python has try-block, within which you can raise exception. Once it's
raised, execution breaks out of the try-block and is caught at the end
of try-block.
Now, Bash has similiar feature. I've added try-block and 'raise'
builtin into Bash-3.0. Typical usage would go something like
try
|
by: djw |
last post by:
c.l.p-
I am having trouble understanding how one is supposed to correctly
utilize try:...except:...finally: in real code. If I have a block of
code like:
def foo():
try:
... some code that can raise an exception ...
|
by: Steve Juranich |
last post by:
I know that this topic has the potential for blowing up in my face,
but I can't help asking. I've been using Python since 1.5.1, so I'm
not what you'd call a "n00b". I dutifully evangelize on the goodness
of Python whenever I talk with fellow developers, but I always hit a
snag when it comes to discussing the finer points of the execution
model (specifically, exceptions).
Without fail, when I start talking with some of the "old-timers"...
|
by: wk6pack |
last post by:
Hi,
I was wondering why when I declare the dim variable outside the try
statement, I could use the .dispose() function but when I declare it inside
the try statement, I get Name 'varname' is not declared.
thanks,
Will
|
by: John Salerno |
last post by:
I'm starting out with this:
try:
if int(text) 0:
return True
else:
self.error_message()
return False
except ValueError:
self.error_message()
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
| |
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
|
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |