WebService "not all code paths return a value" error

J

Jose Fernandez

Hello.
I'm building a web service and I get this error.

NEWS.News.CoverNews(string)': not all code paths return a value

This is the WebMethod

[WebMethod]
public SqlDataReader CoverNews(string Sport)
{
SqlCommand myCommand = new SqlCommand ("SELECT TOP 1 News.idNews FROM
News", myConnection);
myConnection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
if(dr.Read())
{
return dr;
}
myConnection.Close();
}

I don't know how to solve it...
thanks in advance
 
R

RCS

Well, it's true!! Not all code paths return a value!!

[WebMethod]
public SqlDataReader CoverNews(string Sport)
{
SqlCommand myCommand = new SqlCommand ("SELECT TOP 1 News.idNews FROM
News", myConnection);
myConnection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
if(dr.Read())
{
// This will return dr if there IS a row
return dr;
}
myConnection.Close();
// NEW: This will return if there isn't a row
return null;
}
 
J

Jose Fernandez

It compiled OK

BUT

when I run it, I get this error...

System.NullReferenceException: Object reference not set to an instance
of an object.

I can't figure out where it trigger this error

Thanks
 
J

Jon Skeet [C# MVP]

Jose Fernandez said:
It compiled OK

BUT

when I run it, I get this error...

System.NullReferenceException: Object reference not set to an instance
of an object.

I can't figure out where it trigger this error

Print out the stack trace, and you should find out what's causing it.
Consider the possibility that there aren't any rows in the table - so
the modified code is returning null.

Note that you should be closing the command and the reader, either
using try/finally statements or (preferrably IMO) using a using
statement. Also consider what would happen if two requests came in
simultaneously - because the "myConnection" variable is an instance
variable, both requests could try to use the same connection. You
should create, open and close the connection, all within the same
method.
 
S

Sami Vaaraniemi

Jose Fernandez said:
Hello.
I'm building a web service and I get this error.

NEWS.News.CoverNews(string)': not all code paths return a value

This is the WebMethod

[WebMethod]
public SqlDataReader CoverNews(string Sport)
{
SqlCommand myCommand = new SqlCommand ("SELECT TOP 1 News.idNews FROM
News", myConnection);
myConnection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
if(dr.Read())
{
return dr;
}
myConnection.Close();
}

You cannot return an SqlDataReader from a WebMethod. To see what types can
be used as return values or parameters see
http://msdn.microsoft.com/library/d...html/cpcondatatypessupportedbywebservices.asp
(watch for the wrap).

Even if it were possible to return an SqlDataReader from a Web Method, you
wouldn't want to do it as an SqlDataReader uses a live database connection
and you don't want to hand those out to the clients.

As an alternative to returning an SqlDataReader, consider returning either a
DataSet or an array of custom objects. A DataSet (or a typed DataSet) is
convenient but is problematic if non-.NET clients access your Web service.
An array of custom objects is probably your best option.

Regards,
Sami
 
R

RCS

What I put was just an example, you should code that according to your
needs. The initial problem was that not all code paths return a value - and
I was saying that you needed another return statement for the other "case".

And I agree with the other responses too - that this whole chunk of code
(and the return type) could be reengineered a bit!
 
J

Jose Fernandez

Well...
new problems...

I created a News class.
This is...

public class NewsItem
{
private int _NewsId;
private string _NewsTitle;
private string _NewsDate;
private string _PicName;
private string _NewsSummary;

public NewsItem()
{
this._NewsId = NewsId;
this._NewsTitle = NewsTitle;
this._PicName = PicName;
this._NewsSummary= NewsSummary;
}
public NewsItem(int ID, string Title, string PicName, string Summary)
{
this._NewsId = ID;
this._NewsTitle = Title;
this._PicName = PicName;
this._NewsSummary= Summary;
}

public int NewsId
{
get{return _NewsId;}
set{_NewsId=value;}
}

public string NewsTitle
{
get{return _NewsTitle;}
set{_NewsTitle=value;}
}

public string NewsDate
{
get{return _NewsDate;}
set{_NewsDate = value;}
}
public string PicName
{
get{return _PicName;}
set{_PicName = value;}
}
public string NewsSummary
{
get{return _NewsSummary;}
set{_NewsSummary = value;}
}
}

And changed the webmethod like this.

[WebMethod]
public ArrayList CoverNews(string Sport)
{
ArrayList NewsItems = new ArrayList();
SqlConnection myConnection = new SqlConnection("Password=XXX;User
ID=XXX;Initial Catalog=XXX;Data Source=XXX");
SqlCommand myCommand = new SqlCommand ("SELECT TOP 1 PERCENT
News.idNews, News.newsTitle, News.newsSummary, News.newsDate,
NewsPictures.picName, News.SportCat" +
" FROM News INNER JOIN NewsPictures ON News.idPic =
NewsPictures.idPic" +
" WHERE (News.SportCat = 'Sport') ORDER BY News.idNews DESC",
myConnection);
try
{
myCommand.Connection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
while(dr.Read())
{
//NewsItems.Add(new
NewsItem((int)dr["idNews"],dr["NewsTitle"].ToString(),dr["PicName"].ToSt
ring(),dr["NewsSummary"].ToString()));
NewsItems.Add(new NewsItem());
}
}
catch(Exception ex)
{
ex.ToString();
}
finally
{
myCommand.Connection.Close();
}
return NewsItems;
}

I did this following the instructions of the link on microsoft. I
created a Class and made an array of it....
It compiled fine, when I press F5 (Visual Studio) i get tha page that
shows the webservice details and I can see the Method, when I invoke it,
i got an empty XML. Just the header...
"<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfAnyType xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/" /> "

BUT on the microsoft page says
"Class and struct types with public fields or properties. The public
properties and fields are serialized. Classes must have a default
constructor that does not accept any parameters."

Default constructor? How can I assing values to my class without
parameters??

I know that with a Dataset... I solve it, but I don't like Datasets for
small pieces of data. I'm just retrieving 1 news.

Thanks
 
R

RCS

I'm not sure I follow what you are trying to accomplish - but why not just
have a method for getting the news item - like .GetNewsItem(int ID) - and
have that return a populated struct or another class?

What is the ultimate goal - from the consumer-side, what do you want to have
for code - to get the data you want?


Jose Fernandez said:
Well...
new problems...

I created a News class.
This is...

public class NewsItem
{
private int _NewsId;
private string _NewsTitle;
private string _NewsDate;
private string _PicName;
private string _NewsSummary;

public NewsItem()
{
this._NewsId = NewsId;
this._NewsTitle = NewsTitle;
this._PicName = PicName;
this._NewsSummary= NewsSummary;
}
public NewsItem(int ID, string Title, string PicName, string Summary)
{
this._NewsId = ID;
this._NewsTitle = Title;
this._PicName = PicName;
this._NewsSummary= Summary;
}

public int NewsId
{
get{return _NewsId;}
set{_NewsId=value;}
}

public string NewsTitle
{
get{return _NewsTitle;}
set{_NewsTitle=value;}
}

public string NewsDate
{
get{return _NewsDate;}
set{_NewsDate = value;}
}
public string PicName
{
get{return _PicName;}
set{_PicName = value;}
}
public string NewsSummary
{
get{return _NewsSummary;}
set{_NewsSummary = value;}
}
}

And changed the webmethod like this.

[WebMethod]
public ArrayList CoverNews(string Sport)
{
ArrayList NewsItems = new ArrayList();
SqlConnection myConnection = new SqlConnection("Password=XXX;User
ID=XXX;Initial Catalog=XXX;Data Source=XXX");
SqlCommand myCommand = new SqlCommand ("SELECT TOP 1 PERCENT
News.idNews, News.newsTitle, News.newsSummary, News.newsDate,
NewsPictures.picName, News.SportCat" +
" FROM News INNER JOIN NewsPictures ON News.idPic =
NewsPictures.idPic" +
" WHERE (News.SportCat = 'Sport') ORDER BY News.idNews DESC",
myConnection);
try
{
myCommand.Connection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
while(dr.Read())
{
//NewsItems.Add(new
NewsItem((int)dr["idNews"],dr["NewsTitle"].ToString(),dr["PicName"].ToSt
ring(),dr["NewsSummary"].ToString()));
NewsItems.Add(new NewsItem());
}
}
catch(Exception ex)
{
ex.ToString();
}
finally
{
myCommand.Connection.Close();
}
return NewsItems;
}

I did this following the instructions of the link on microsoft. I
created a Class and made an array of it....
It compiled fine, when I press F5 (Visual Studio) i get tha page that
shows the webservice details and I can see the Method, when I invoke it,
i got an empty XML. Just the header...
"<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfAnyType xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/" /> "

BUT on the microsoft page says
"Class and struct types with public fields or properties. The public
properties and fields are serialized. Classes must have a default
constructor that does not accept any parameters."

Default constructor? How can I assing values to my class without
parameters??

I know that with a Dataset... I solve it, but I don't like Datasets for
small pieces of data. I'm just retrieving 1 news.

Thanks
 
D

DalePres

To return a NewsItem from your webservice, add the [XMLInclude] attribute
before the declaration of the NewsItem class.

I think what may be confusing you about the public default constructor is
this: If you create a constructor with parameters, then no default
construct will be automatically created; you will have to manually create
one. If you do not create any constructor, then a default will be created
automatically. That tidbit may or may not have anything to do with your
problem though.

Here's how I implemented a very simple web service returning a NewsItem to a
web page:

First, the NewsItem class that I created as a public class in the WebService
namespace and file but not within the webservice class:

public class NewsItem

{

private int _NewsId;

private string _NewsTitle;

private string _NewsDate;

private string _PicName;

private string _NewsSummary;

public NewsItem()

{

}

public int NewsId

{

get{return _NewsId;}

set{_NewsId=value;}

}

public string NewsTitle

{

get{return _NewsTitle;}

set{_NewsTitle=value;}

}

public string NewsDate

{

get{return _NewsDate;}

set{_NewsDate = value;}

}

public string PicName

{

get{return _PicName;}

set{_PicName = value;}

}

public string NewsSummary

{

get{return _NewsSummary;}

set{_NewsSummary = value;}

}

}



Next, I added these lines to the Page_Load method of an otherwise blank
webform:

NewsService.Service1 news = new WebApplication2.NewsService.Service1();

news.Credentials = System.Net.CredentialCache.DefaultCredentials;

news.NewsItem item = news.GetItem();

Response.Write(item.NewsSummary);



And then last, I created this WebMethod:

[WebMethod]

[XmlInclude(typeof(NewsItem))]

public NewsItem GetItem()

{

NewsItem item = new NewsItem();

item.NewsDate = "02/05/2005";

item.NewsId = 1;

item.NewsSummary = "No one was killed today.";

item.NewsTitle = "Special Report!";

item.PicName = "NewBornBaby.jpg";

return item;

}



Now, when I run the project, the phrase "No one was killed today." is
displayed as expected. We have successfully returned a custom class
NewsItem from our web service. This is one method of doing so, where we
instantiate on the web service client (the asp.net web application) an
object NewsItem defined in the web service.

Another way I successfully passed a NewsItem from a web service to my
webform involves the following changes:



1. Copy the NewsItem class from the web service file and paste it into the
aspx file, within the project namespace but outside of the webform class.
Now you have the NewsItem class available locally for the webform.



2. The third line of the code for the Page_Load above, remove the "news." at
the beginning. Now we want to instantiate the local copy of the NewsItem
class, rather than the copy at the web service.



3. In the project explorer, make sure you are showing all files and browse
to the Reference.cs file for your web service. Edit all references to the
word NewsItem to read YourNameSpace.NewsItem, except for one reference to
the word - the one that should be the last reference and it starts with
public class NewsItem. This reference is just below an attribute similar to

[System.Xml.Serialization.XmlTypeAttribute(Namespace=http://tempuri.org/)]

though yours may have a different namespace.

4. Now if you compile your app and run it again, you will instantiate a
NewsItem from your local copy of the class but it will still accept the
NewsItem returned by the web service and your web form will still display
the phrase "No one was killed today."

All that is left is for you to flush out how to set the properties of the
NewsItems. Though I didn't do it in this example, I have used both these
methods in the past to create arrays of custom classes and successfully pass
them between a web service and ASP.Net. Remember that this behavior does
not follow the W3C guidelines for WebServices and clients other than ASP.Net
may not be able to consume your NewsItem web service.

One last point. If you choose the second route, where you modify the
Reference.cs file, keep in mind that any time you update the web reference
in Visual Studio, the Reference.cs file is re-created and you will have to
make your changes to that file again.

Hope this helps,



DalePres

MCAD, MCDBA, MCSE



Jose Fernandez said:
Well...
new problems...

I created a News class.
This is...

public class NewsItem
{
private int _NewsId;
private string _NewsTitle;
private string _NewsDate;
private string _PicName;
private string _NewsSummary;

public NewsItem()
{
this._NewsId = NewsId;
this._NewsTitle = NewsTitle;
this._PicName = PicName;
this._NewsSummary= NewsSummary;
}
public NewsItem(int ID, string Title, string PicName, string Summary)
{
this._NewsId = ID;
this._NewsTitle = Title;
this._PicName = PicName;
this._NewsSummary= Summary;
}

public int NewsId
{
get{return _NewsId;}
set{_NewsId=value;}
}

public string NewsTitle
{
get{return _NewsTitle;}
set{_NewsTitle=value;}
}

public string NewsDate
{
get{return _NewsDate;}
set{_NewsDate = value;}
}
public string PicName
{
get{return _PicName;}
set{_PicName = value;}
}
public string NewsSummary
{
get{return _NewsSummary;}
set{_NewsSummary = value;}
}
}

And changed the webmethod like this.

[WebMethod]
public ArrayList CoverNews(string Sport)
{
ArrayList NewsItems = new ArrayList();
SqlConnection myConnection = new SqlConnection("Password=XXX;User
ID=XXX;Initial Catalog=XXX;Data Source=XXX");
SqlCommand myCommand = new SqlCommand ("SELECT TOP 1 PERCENT
News.idNews, News.newsTitle, News.newsSummary, News.newsDate,
NewsPictures.picName, News.SportCat" +
" FROM News INNER JOIN NewsPictures ON News.idPic =
NewsPictures.idPic" +
" WHERE (News.SportCat = 'Sport') ORDER BY News.idNews DESC",
myConnection);
try
{
myCommand.Connection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
while(dr.Read())
{
//NewsItems.Add(new
NewsItem((int)dr["idNews"],dr["NewsTitle"].ToString(),dr["PicName"].ToSt
ring(),dr["NewsSummary"].ToString()));
NewsItems.Add(new NewsItem());
}
}
catch(Exception ex)
{
ex.ToString();
}
finally
{
myCommand.Connection.Close();
}
return NewsItems;
}

I did this following the instructions of the link on microsoft. I
created a Class and made an array of it....
It compiled fine, when I press F5 (Visual Studio) i get tha page that
shows the webservice details and I can see the Method, when I invoke it,
i got an empty XML. Just the header...
"<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfAnyType xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/" /> "

BUT on the microsoft page says
"Class and struct types with public fields or properties. The public
properties and fields are serialized. Classes must have a default
constructor that does not accept any parameters."

Default constructor? How can I assing values to my class without
parameters??

I know that with a Dataset... I solve it, but I don't like Datasets for
small pieces of data. I'm just retrieving 1 news.

Thanks
 
D

DalePres

A quick correction to my first post. Add the XmlInclude to your webmethod,
not to the NewsItem class. The sample I created shows it correctly.

DalePres

DalePres said:
To return a NewsItem from your webservice, add the [XMLInclude] attribute
before the declaration of the NewsItem class.

I think what may be confusing you about the public default constructor is
this: If you create a constructor with parameters, then no default
construct will be automatically created; you will have to manually create
one. If you do not create any constructor, then a default will be created
automatically. That tidbit may or may not have anything to do with your
problem though.

Here's how I implemented a very simple web service returning a NewsItem to
a web page:

First, the NewsItem class that I created as a public class in the
WebService namespace and file but not within the webservice class:

public class NewsItem

{

private int _NewsId;

private string _NewsTitle;

private string _NewsDate;

private string _PicName;

private string _NewsSummary;

public NewsItem()

{

}

public int NewsId

{

get{return _NewsId;}

set{_NewsId=value;}

}

public string NewsTitle

{

get{return _NewsTitle;}

set{_NewsTitle=value;}

}

public string NewsDate

{

get{return _NewsDate;}

set{_NewsDate = value;}

}

public string PicName

{

get{return _PicName;}

set{_PicName = value;}

}

public string NewsSummary

{

get{return _NewsSummary;}

set{_NewsSummary = value;}

}

}



Next, I added these lines to the Page_Load method of an otherwise blank
webform:

NewsService.Service1 news = new WebApplication2.NewsService.Service1();

news.Credentials = System.Net.CredentialCache.DefaultCredentials;

news.NewsItem item = news.GetItem();

Response.Write(item.NewsSummary);



And then last, I created this WebMethod:

[WebMethod]

[XmlInclude(typeof(NewsItem))]

public NewsItem GetItem()

{

NewsItem item = new NewsItem();

item.NewsDate = "02/05/2005";

item.NewsId = 1;

item.NewsSummary = "No one was killed today.";

item.NewsTitle = "Special Report!";

item.PicName = "NewBornBaby.jpg";

return item;

}



Now, when I run the project, the phrase "No one was killed today." is
displayed as expected. We have successfully returned a custom class
NewsItem from our web service. This is one method of doing so, where we
instantiate on the web service client (the asp.net web application) an
object NewsItem defined in the web service.

Another way I successfully passed a NewsItem from a web service to my
webform involves the following changes:



1. Copy the NewsItem class from the web service file and paste it into the
aspx file, within the project namespace but outside of the webform class.
Now you have the NewsItem class available locally for the webform.



2. The third line of the code for the Page_Load above, remove the "news."
at the beginning. Now we want to instantiate the local copy of the
NewsItem class, rather than the copy at the web service.



3. In the project explorer, make sure you are showing all files and browse
to the Reference.cs file for your web service. Edit all references to the
word NewsItem to read YourNameSpace.NewsItem, except for one reference to
the word - the one that should be the last reference and it starts with
public class NewsItem. This reference is just below an attribute similar
to

[System.Xml.Serialization.XmlTypeAttribute(Namespace=http://tempuri.org/)]

though yours may have a different namespace.

4. Now if you compile your app and run it again, you will instantiate a
NewsItem from your local copy of the class but it will still accept the
NewsItem returned by the web service and your web form will still display
the phrase "No one was killed today."

All that is left is for you to flush out how to set the properties of the
NewsItems. Though I didn't do it in this example, I have used both these
methods in the past to create arrays of custom classes and successfully
pass them between a web service and ASP.Net. Remember that this behavior
does not follow the W3C guidelines for WebServices and clients other than
ASP.Net may not be able to consume your NewsItem web service.

One last point. If you choose the second route, where you modify the
Reference.cs file, keep in mind that any time you update the web reference
in Visual Studio, the Reference.cs file is re-created and you will have to
make your changes to that file again.

Hope this helps,



DalePres

MCAD, MCDBA, MCSE



Jose Fernandez said:
Well...
new problems...

I created a News class.
This is...

public class NewsItem
{
private int _NewsId;
private string _NewsTitle;
private string _NewsDate;
private string _PicName;
private string _NewsSummary;

public NewsItem()
{
this._NewsId = NewsId;
this._NewsTitle = NewsTitle;
this._PicName = PicName;
this._NewsSummary= NewsSummary;
}
public NewsItem(int ID, string Title, string PicName, string Summary)
{
this._NewsId = ID;
this._NewsTitle = Title;
this._PicName = PicName;
this._NewsSummary= Summary;
}

public int NewsId
{
get{return _NewsId;}
set{_NewsId=value;}
}

public string NewsTitle
{
get{return _NewsTitle;}
set{_NewsTitle=value;}
}

public string NewsDate
{
get{return _NewsDate;}
set{_NewsDate = value;}
}
public string PicName
{
get{return _PicName;}
set{_PicName = value;}
}
public string NewsSummary
{
get{return _NewsSummary;}
set{_NewsSummary = value;}
}
}

And changed the webmethod like this.

[WebMethod]
public ArrayList CoverNews(string Sport)
{
ArrayList NewsItems = new ArrayList();
SqlConnection myConnection = new SqlConnection("Password=XXX;User
ID=XXX;Initial Catalog=XXX;Data Source=XXX");
SqlCommand myCommand = new SqlCommand ("SELECT TOP 1 PERCENT
News.idNews, News.newsTitle, News.newsSummary, News.newsDate,
NewsPictures.picName, News.SportCat" +
" FROM News INNER JOIN NewsPictures ON News.idPic =
NewsPictures.idPic" +
" WHERE (News.SportCat = 'Sport') ORDER BY News.idNews DESC",
myConnection);
try
{
myCommand.Connection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
while(dr.Read())
{
//NewsItems.Add(new
NewsItem((int)dr["idNews"],dr["NewsTitle"].ToString(),dr["PicName"].ToSt
ring(),dr["NewsSummary"].ToString()));
NewsItems.Add(new NewsItem());
}
}
catch(Exception ex)
{
ex.ToString();
}
finally
{
myCommand.Connection.Close();
}
return NewsItems;
}

I did this following the instructions of the link on microsoft. I
created a Class and made an array of it....
It compiled fine, when I press F5 (Visual Studio) i get tha page that
shows the webservice details and I can see the Method, when I invoke it,
i got an empty XML. Just the header...
"<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfAnyType xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/" /> "

BUT on the microsoft page says
"Class and struct types with public fields or properties. The public
properties and fields are serialized. Classes must have a default
constructor that does not accept any parameters."

Default constructor? How can I assing values to my class without
parameters??

I know that with a Dataset... I solve it, but I don't like Datasets for
small pieces of data. I'm just retrieving 1 news.

Thanks
 
S

Sami Vaaraniemi

The XmlInclude attribute is only needed for polymorphic return or parameter
types - which is not the case here.

To return a single NewsItem DalePres's sample code is fine except that the
XmlInclude attribute is not needed.

If you want to return multiple NewsItems, don't return an ArrayList, it is
not supported. Return an array of custom objects instead:

[WebMethod]
public NewsItem[] CoverNews(string Sport)
{
ArrayList NewsItems = new ArrayList();

// populate ArrayList with NewsItems here...

return (NewsItem[])NewsItems.ToArray(typeof(NewsItem));
}

Regards,
Sami

DalePres said:
To return a NewsItem from your webservice, add the [XMLInclude] attribute
before the declaration of the NewsItem class.

I think what may be confusing you about the public default constructor is
this: If you create a constructor with parameters, then no default
construct will be automatically created; you will have to manually create
one. If you do not create any constructor, then a default will be created
automatically. That tidbit may or may not have anything to do with your
problem though.

Here's how I implemented a very simple web service returning a NewsItem to
a web page:

First, the NewsItem class that I created as a public class in the
WebService namespace and file but not within the webservice class:

public class NewsItem

{

private int _NewsId;

private string _NewsTitle;

private string _NewsDate;

private string _PicName;

private string _NewsSummary;

public NewsItem()

{

}

public int NewsId

{

get{return _NewsId;}

set{_NewsId=value;}

}

public string NewsTitle

{

get{return _NewsTitle;}

set{_NewsTitle=value;}

}

public string NewsDate

{

get{return _NewsDate;}

set{_NewsDate = value;}

}

public string PicName

{

get{return _PicName;}

set{_PicName = value;}

}

public string NewsSummary

{

get{return _NewsSummary;}

set{_NewsSummary = value;}

}

}



Next, I added these lines to the Page_Load method of an otherwise blank
webform:

NewsService.Service1 news = new WebApplication2.NewsService.Service1();

news.Credentials = System.Net.CredentialCache.DefaultCredentials;

news.NewsItem item = news.GetItem();

Response.Write(item.NewsSummary);



And then last, I created this WebMethod:

[WebMethod]

[XmlInclude(typeof(NewsItem))]

public NewsItem GetItem()

{

NewsItem item = new NewsItem();

item.NewsDate = "02/05/2005";

item.NewsId = 1;

item.NewsSummary = "No one was killed today.";

item.NewsTitle = "Special Report!";

item.PicName = "NewBornBaby.jpg";

return item;

}



Now, when I run the project, the phrase "No one was killed today." is
displayed as expected. We have successfully returned a custom class
NewsItem from our web service. This is one method of doing so, where we
instantiate on the web service client (the asp.net web application) an
object NewsItem defined in the web service.

Another way I successfully passed a NewsItem from a web service to my
webform involves the following changes:



1. Copy the NewsItem class from the web service file and paste it into the
aspx file, within the project namespace but outside of the webform class.
Now you have the NewsItem class available locally for the webform.



2. The third line of the code for the Page_Load above, remove the "news."
at the beginning. Now we want to instantiate the local copy of the
NewsItem class, rather than the copy at the web service.



3. In the project explorer, make sure you are showing all files and browse
to the Reference.cs file for your web service. Edit all references to the
word NewsItem to read YourNameSpace.NewsItem, except for one reference to
the word - the one that should be the last reference and it starts with
public class NewsItem. This reference is just below an attribute similar
to

[System.Xml.Serialization.XmlTypeAttribute(Namespace=http://tempuri.org/)]

though yours may have a different namespace.

4. Now if you compile your app and run it again, you will instantiate a
NewsItem from your local copy of the class but it will still accept the
NewsItem returned by the web service and your web form will still display
the phrase "No one was killed today."

All that is left is for you to flush out how to set the properties of the
NewsItems. Though I didn't do it in this example, I have used both these
methods in the past to create arrays of custom classes and successfully
pass them between a web service and ASP.Net. Remember that this behavior
does not follow the W3C guidelines for WebServices and clients other than
ASP.Net may not be able to consume your NewsItem web service.

One last point. If you choose the second route, where you modify the
Reference.cs file, keep in mind that any time you update the web reference
in Visual Studio, the Reference.cs file is re-created and you will have to
make your changes to that file again.

Hope this helps,



DalePres

MCAD, MCDBA, MCSE



Jose Fernandez said:
Well...
new problems...

I created a News class.
This is...

public class NewsItem
{
private int _NewsId;
private string _NewsTitle;
private string _NewsDate;
private string _PicName;
private string _NewsSummary;

public NewsItem()
{
this._NewsId = NewsId;
this._NewsTitle = NewsTitle;
this._PicName = PicName;
this._NewsSummary= NewsSummary;
}
public NewsItem(int ID, string Title, string PicName, string Summary)
{
this._NewsId = ID;
this._NewsTitle = Title;
this._PicName = PicName;
this._NewsSummary= Summary;
}

public int NewsId
{
get{return _NewsId;}
set{_NewsId=value;}
}

public string NewsTitle
{
get{return _NewsTitle;}
set{_NewsTitle=value;}
}

public string NewsDate
{
get{return _NewsDate;}
set{_NewsDate = value;}
}
public string PicName
{
get{return _PicName;}
set{_PicName = value;}
}
public string NewsSummary
{
get{return _NewsSummary;}
set{_NewsSummary = value;}
}
}

And changed the webmethod like this.

[WebMethod]
public ArrayList CoverNews(string Sport)
{
ArrayList NewsItems = new ArrayList();
SqlConnection myConnection = new SqlConnection("Password=XXX;User
ID=XXX;Initial Catalog=XXX;Data Source=XXX");
SqlCommand myCommand = new SqlCommand ("SELECT TOP 1 PERCENT
News.idNews, News.newsTitle, News.newsSummary, News.newsDate,
NewsPictures.picName, News.SportCat" +
" FROM News INNER JOIN NewsPictures ON News.idPic =
NewsPictures.idPic" +
" WHERE (News.SportCat = 'Sport') ORDER BY News.idNews DESC",
myConnection);
try
{
myCommand.Connection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
while(dr.Read())
{
//NewsItems.Add(new
NewsItem((int)dr["idNews"],dr["NewsTitle"].ToString(),dr["PicName"].ToSt
ring(),dr["NewsSummary"].ToString()));
NewsItems.Add(new NewsItem());
}
}
catch(Exception ex)
{
ex.ToString();
}
finally
{
myCommand.Connection.Close();
}
return NewsItems;
}

I did this following the instructions of the link on microsoft. I
created a Class and made an array of it....
It compiled fine, when I press F5 (Visual Studio) i get tha page that
shows the webservice details and I can see the Method, when I invoke it,
i got an empty XML. Just the header...
"<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfAnyType xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/" /> "

BUT on the microsoft page says
"Class and struct types with public fields or properties. The public
properties and fields are serialized. Classes must have a default
constructor that does not accept any parameters."

Default constructor? How can I assing values to my class without
parameters??

I know that with a Dataset... I solve it, but I don't like Datasets for
small pieces of data. I'm just retrieving 1 news.

Thanks
 
D

DalePres

Good point. I had forgotten that when I did this before, I was using out
parameters of objects. I just threw all I remembered of the solution into
this example for Jose.

DalePres

Sami Vaaraniemi said:
The XmlInclude attribute is only needed for polymorphic return or
parameter types - which is not the case here.

To return a single NewsItem DalePres's sample code is fine except that the
XmlInclude attribute is not needed.

If you want to return multiple NewsItems, don't return an ArrayList, it is
not supported. Return an array of custom objects instead:

[WebMethod]
public NewsItem[] CoverNews(string Sport)
{
ArrayList NewsItems = new ArrayList();

// populate ArrayList with NewsItems here...

return (NewsItem[])NewsItems.ToArray(typeof(NewsItem));
}

Regards,
Sami

DalePres said:
To return a NewsItem from your webservice, add the [XMLInclude] attribute
before the declaration of the NewsItem class.

I think what may be confusing you about the public default constructor is
this: If you create a constructor with parameters, then no default
construct will be automatically created; you will have to manually create
one. If you do not create any constructor, then a default will be
created automatically. That tidbit may or may not have anything to do
with your problem though.

Here's how I implemented a very simple web service returning a NewsItem
to a web page:

First, the NewsItem class that I created as a public class in the
WebService namespace and file but not within the webservice class:

public class NewsItem

{

private int _NewsId;

private string _NewsTitle;

private string _NewsDate;

private string _PicName;

private string _NewsSummary;

public NewsItem()

{

}

public int NewsId

{

get{return _NewsId;}

set{_NewsId=value;}

}

public string NewsTitle

{

get{return _NewsTitle;}

set{_NewsTitle=value;}

}

public string NewsDate

{

get{return _NewsDate;}

set{_NewsDate = value;}

}

public string PicName

{

get{return _PicName;}

set{_PicName = value;}

}

public string NewsSummary

{

get{return _NewsSummary;}

set{_NewsSummary = value;}

}

}



Next, I added these lines to the Page_Load method of an otherwise blank
webform:

NewsService.Service1 news = new WebApplication2.NewsService.Service1();

news.Credentials = System.Net.CredentialCache.DefaultCredentials;

news.NewsItem item = news.GetItem();

Response.Write(item.NewsSummary);



And then last, I created this WebMethod:

[WebMethod]

[XmlInclude(typeof(NewsItem))]

public NewsItem GetItem()

{

NewsItem item = new NewsItem();

item.NewsDate = "02/05/2005";

item.NewsId = 1;

item.NewsSummary = "No one was killed today.";

item.NewsTitle = "Special Report!";

item.PicName = "NewBornBaby.jpg";

return item;

}



Now, when I run the project, the phrase "No one was killed today." is
displayed as expected. We have successfully returned a custom class
NewsItem from our web service. This is one method of doing so, where we
instantiate on the web service client (the asp.net web application) an
object NewsItem defined in the web service.

Another way I successfully passed a NewsItem from a web service to my
webform involves the following changes:



1. Copy the NewsItem class from the web service file and paste it into
the aspx file, within the project namespace but outside of the webform
class. Now you have the NewsItem class available locally for the webform.



2. The third line of the code for the Page_Load above, remove the "news."
at the beginning. Now we want to instantiate the local copy of the
NewsItem class, rather than the copy at the web service.



3. In the project explorer, make sure you are showing all files and
browse to the Reference.cs file for your web service. Edit all
references to the word NewsItem to read YourNameSpace.NewsItem, except
for one reference to the word - the one that should be the last reference
and it starts with public class NewsItem. This reference is just below
an attribute similar to

[System.Xml.Serialization.XmlTypeAttribute(Namespace=http://tempuri.org/)]

though yours may have a different namespace.

4. Now if you compile your app and run it again, you will instantiate a
NewsItem from your local copy of the class but it will still accept the
NewsItem returned by the web service and your web form will still display
the phrase "No one was killed today."

All that is left is for you to flush out how to set the properties of the
NewsItems. Though I didn't do it in this example, I have used both these
methods in the past to create arrays of custom classes and successfully
pass them between a web service and ASP.Net. Remember that this behavior
does not follow the W3C guidelines for WebServices and clients other than
ASP.Net may not be able to consume your NewsItem web service.

One last point. If you choose the second route, where you modify the
Reference.cs file, keep in mind that any time you update the web
reference in Visual Studio, the Reference.cs file is re-created and you
will have to make your changes to that file again.

Hope this helps,



DalePres

MCAD, MCDBA, MCSE



Jose Fernandez said:
Well...
new problems...

I created a News class.
This is...

public class NewsItem
{
private int _NewsId;
private string _NewsTitle;
private string _NewsDate;
private string _PicName;
private string _NewsSummary;

public NewsItem()
{
this._NewsId = NewsId;
this._NewsTitle = NewsTitle;
this._PicName = PicName;
this._NewsSummary= NewsSummary;
}
public NewsItem(int ID, string Title, string PicName, string Summary)
{
this._NewsId = ID;
this._NewsTitle = Title;
this._PicName = PicName;
this._NewsSummary= Summary;
}

public int NewsId
{
get{return _NewsId;}
set{_NewsId=value;}
}

public string NewsTitle
{
get{return _NewsTitle;}
set{_NewsTitle=value;}
}

public string NewsDate
{
get{return _NewsDate;}
set{_NewsDate = value;}
}
public string PicName
{
get{return _PicName;}
set{_PicName = value;}
}
public string NewsSummary
{
get{return _NewsSummary;}
set{_NewsSummary = value;}
}
}

And changed the webmethod like this.

[WebMethod]
public ArrayList CoverNews(string Sport)
{
ArrayList NewsItems = new ArrayList();
SqlConnection myConnection = new SqlConnection("Password=XXX;User
ID=XXX;Initial Catalog=XXX;Data Source=XXX");
SqlCommand myCommand = new SqlCommand ("SELECT TOP 1 PERCENT
News.idNews, News.newsTitle, News.newsSummary, News.newsDate,
NewsPictures.picName, News.SportCat" +
" FROM News INNER JOIN NewsPictures ON News.idPic =
NewsPictures.idPic" +
" WHERE (News.SportCat = 'Sport') ORDER BY News.idNews DESC",
myConnection);
try
{
myCommand.Connection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
while(dr.Read())
{
//NewsItems.Add(new
NewsItem((int)dr["idNews"],dr["NewsTitle"].ToString(),dr["PicName"].ToSt
ring(),dr["NewsSummary"].ToString()));
NewsItems.Add(new NewsItem());
}
}
catch(Exception ex)
{
ex.ToString();
}
finally
{
myCommand.Connection.Close();
}
return NewsItems;
}

I did this following the instructions of the link on microsoft. I
created a Class and made an array of it....
It compiled fine, when I press F5 (Visual Studio) i get tha page that
shows the webservice details and I can see the Method, when I invoke it,
i got an empty XML. Just the header...
"<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfAnyType xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/" /> "

BUT on the microsoft page says
"Class and struct types with public fields or properties. The public
properties and fields are serialized. Classes must have a default
constructor that does not accept any parameters."

Default constructor? How can I assing values to my class without
parameters??

I know that with a Dataset... I solve it, but I don't like Datasets for
small pieces of data. I'm just retrieving 1 news.

Thanks
 
D

DalePres

Ok...I tested it again and don't need the XmlInclude at all. I will have to
go back to the drawing board on that attribute and figure it out all over
again. I am able to pass objects and even objects that include objects - if
those objects are all made up of serializable types - between web services
and asp.net.

DalePres


Sami Vaaraniemi said:
The XmlInclude attribute is only needed for polymorphic return or
parameter types - which is not the case here.

To return a single NewsItem DalePres's sample code is fine except that the
XmlInclude attribute is not needed.

If you want to return multiple NewsItems, don't return an ArrayList, it is
not supported. Return an array of custom objects instead:

[WebMethod]
public NewsItem[] CoverNews(string Sport)
{
ArrayList NewsItems = new ArrayList();

// populate ArrayList with NewsItems here...

return (NewsItem[])NewsItems.ToArray(typeof(NewsItem));
}

Regards,
Sami

DalePres said:
To return a NewsItem from your webservice, add the [XMLInclude] attribute
before the declaration of the NewsItem class.

I think what may be confusing you about the public default constructor is
this: If you create a constructor with parameters, then no default
construct will be automatically created; you will have to manually create
one. If you do not create any constructor, then a default will be
created automatically. That tidbit may or may not have anything to do
with your problem though.

Here's how I implemented a very simple web service returning a NewsItem
to a web page:

First, the NewsItem class that I created as a public class in the
WebService namespace and file but not within the webservice class:

public class NewsItem

{

private int _NewsId;

private string _NewsTitle;

private string _NewsDate;

private string _PicName;

private string _NewsSummary;

public NewsItem()

{

}

public int NewsId

{

get{return _NewsId;}

set{_NewsId=value;}

}

public string NewsTitle

{

get{return _NewsTitle;}

set{_NewsTitle=value;}

}

public string NewsDate

{

get{return _NewsDate;}

set{_NewsDate = value;}

}

public string PicName

{

get{return _PicName;}

set{_PicName = value;}

}

public string NewsSummary

{

get{return _NewsSummary;}

set{_NewsSummary = value;}

}

}



Next, I added these lines to the Page_Load method of an otherwise blank
webform:

NewsService.Service1 news = new WebApplication2.NewsService.Service1();

news.Credentials = System.Net.CredentialCache.DefaultCredentials;

news.NewsItem item = news.GetItem();

Response.Write(item.NewsSummary);



And then last, I created this WebMethod:

[WebMethod]

[XmlInclude(typeof(NewsItem))]

public NewsItem GetItem()

{

NewsItem item = new NewsItem();

item.NewsDate = "02/05/2005";

item.NewsId = 1;

item.NewsSummary = "No one was killed today.";

item.NewsTitle = "Special Report!";

item.PicName = "NewBornBaby.jpg";

return item;

}



Now, when I run the project, the phrase "No one was killed today." is
displayed as expected. We have successfully returned a custom class
NewsItem from our web service. This is one method of doing so, where we
instantiate on the web service client (the asp.net web application) an
object NewsItem defined in the web service.

Another way I successfully passed a NewsItem from a web service to my
webform involves the following changes:



1. Copy the NewsItem class from the web service file and paste it into
the aspx file, within the project namespace but outside of the webform
class. Now you have the NewsItem class available locally for the webform.



2. The third line of the code for the Page_Load above, remove the "news."
at the beginning. Now we want to instantiate the local copy of the
NewsItem class, rather than the copy at the web service.



3. In the project explorer, make sure you are showing all files and
browse to the Reference.cs file for your web service. Edit all
references to the word NewsItem to read YourNameSpace.NewsItem, except
for one reference to the word - the one that should be the last reference
and it starts with public class NewsItem. This reference is just below
an attribute similar to

[System.Xml.Serialization.XmlTypeAttribute(Namespace=http://tempuri.org/)]

though yours may have a different namespace.

4. Now if you compile your app and run it again, you will instantiate a
NewsItem from your local copy of the class but it will still accept the
NewsItem returned by the web service and your web form will still display
the phrase "No one was killed today."

All that is left is for you to flush out how to set the properties of the
NewsItems. Though I didn't do it in this example, I have used both these
methods in the past to create arrays of custom classes and successfully
pass them between a web service and ASP.Net. Remember that this behavior
does not follow the W3C guidelines for WebServices and clients other than
ASP.Net may not be able to consume your NewsItem web service.

One last point. If you choose the second route, where you modify the
Reference.cs file, keep in mind that any time you update the web
reference in Visual Studio, the Reference.cs file is re-created and you
will have to make your changes to that file again.

Hope this helps,



DalePres

MCAD, MCDBA, MCSE



Jose Fernandez said:
Well...
new problems...

I created a News class.
This is...

public class NewsItem
{
private int _NewsId;
private string _NewsTitle;
private string _NewsDate;
private string _PicName;
private string _NewsSummary;

public NewsItem()
{
this._NewsId = NewsId;
this._NewsTitle = NewsTitle;
this._PicName = PicName;
this._NewsSummary= NewsSummary;
}
public NewsItem(int ID, string Title, string PicName, string Summary)
{
this._NewsId = ID;
this._NewsTitle = Title;
this._PicName = PicName;
this._NewsSummary= Summary;
}

public int NewsId
{
get{return _NewsId;}
set{_NewsId=value;}
}

public string NewsTitle
{
get{return _NewsTitle;}
set{_NewsTitle=value;}
}

public string NewsDate
{
get{return _NewsDate;}
set{_NewsDate = value;}
}
public string PicName
{
get{return _PicName;}
set{_PicName = value;}
}
public string NewsSummary
{
get{return _NewsSummary;}
set{_NewsSummary = value;}
}
}

And changed the webmethod like this.

[WebMethod]
public ArrayList CoverNews(string Sport)
{
ArrayList NewsItems = new ArrayList();
SqlConnection myConnection = new SqlConnection("Password=XXX;User
ID=XXX;Initial Catalog=XXX;Data Source=XXX");
SqlCommand myCommand = new SqlCommand ("SELECT TOP 1 PERCENT
News.idNews, News.newsTitle, News.newsSummary, News.newsDate,
NewsPictures.picName, News.SportCat" +
" FROM News INNER JOIN NewsPictures ON News.idPic =
NewsPictures.idPic" +
" WHERE (News.SportCat = 'Sport') ORDER BY News.idNews DESC",
myConnection);
try
{
myCommand.Connection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
while(dr.Read())
{
//NewsItems.Add(new
NewsItem((int)dr["idNews"],dr["NewsTitle"].ToString(),dr["PicName"].ToSt
ring(),dr["NewsSummary"].ToString()));
NewsItems.Add(new NewsItem());
}
}
catch(Exception ex)
{
ex.ToString();
}
finally
{
myCommand.Connection.Close();
}
return NewsItems;
}

I did this following the instructions of the link on microsoft. I
created a Class and made an array of it....
It compiled fine, when I press F5 (Visual Studio) i get tha page that
shows the webservice details and I can see the Method, when I invoke it,
i got an empty XML. Just the header...
"<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfAnyType xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/" /> "

BUT on the microsoft page says
"Class and struct types with public fields or properties. The public
properties and fields are serialized. Classes must have a default
constructor that does not accept any parameters."

Default constructor? How can I assing values to my class without
parameters??

I know that with a Dataset... I solve it, but I don't like Datasets for
small pieces of data. I'm just retrieving 1 news.

Thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top