Return multiple values with web service - c#

I am trying to learn web services. My problem is I have created a class "Item" as follows,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WebServiceTaxCalc
{
public enum Type { BASIC, IMPORTED, EXEMPT}
public class Item
{
string name;
double basePrice;
int quantity;
Type TaxType;
public Item(string name, double price, int quantity, Type type)
{
this.basePrice = price;
this.name = name;
this.quantity = quantity;
this.TaxType = type;
}
public string getName()
{
return name;
}
public double getPrice()
{ return basePrice; }
public int getQuantity()
{ return quantity; }
public Type getType() { return TaxType; }
}
}
and another class for calculating the tax:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WebServiceTaxCalc
{
public class ShoppingBasket
{
double itemsTotalPrice = 0.0;
double totalTax = 0.0;
public void addItem(List<Item> i)
{
foreach (Item a in i)
{
totalTax += taxPerItem(a);
double eachItemPrice = (a.getPrice() + taxPerItem(a));
itemsTotalPrice += eachItemPrice;
//Console.WriteLine(a.getQuantity() + " " + a.getName() + ": " + eachItemPrice);
}
//Console.WriteLine("sales tax: " + totalTax);
//Console.WriteLine("total cost: "+itemsTotalPrice);
}
public double taxPerItem(Item i)
{
double tax = 0;
if (i.getType() == Type.BASIC)
{
tax = i.getPrice() * 5 / 100;
return tax;
}
else if (i.getType() == Type.EXEMPT)
{
tax = 0;
return tax;
}
else
{
tax = i.getPrice() * 15 / 100;
return tax;
}
}
}
}
I am trying to pass the values to the web service and let the web service call the classes.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
namespace WebServiceTaxCalc
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public ShoppingBasket Calc(string name, double price, int quantity, Type catg)
{
List<Item> l1 = new List<Item>();
Item i1 = new Item(name, price, quantity,catg);
l1.Add(i1);
ShoppingBasket sb = new ShoppingBasket();
sb.addItem(l1);
return sb;
}
}
}
I am giving the input like this,
input image:
and after invoking I am just getting this:
Output image
I am not getting the document tree of what I passed.
I have seen a useful post here https://stackoverflow.com/a/12039010/3768995
But I couldn't solve my problem.
Please guide me through this.

Add a [DataContract] attribute to ShoppingBasket and a [DataMember] attribute to the properties that need to be included when the response is sent. (And as was said, make them public properties.)

Related

Multiple foreach passes to different class lists

I'm working on a "bank application" in C# WPF where I came upon error:CS0052
Inconsistent accessibility: field type 'List' is less
accessible than field 'Customer.CustomerAccountsList'
The idea is that the method bool DoseThisAccountExistAlready() should check all customers one by one and see if his/her accounts have the same data as the account that is about to be created.
However CustomerAccountsList must be public or DoseThisAccountExistAlready() can't access the accounts data.
How do I fix this error?
//main window
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Uppgift2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public List<Customer> ListOfAllCustomers = new List<Customer>();
public bool Login(string fornamn, string efternamn, string pin)
{
foreach (Customer c in ListOfAllCustomers)
{
if (c.firstname == fornamn && c.lastname == efternamn && c.pinKod == pin)
{
MessageBox.Show("Login succesfull. Welcome " + c.firstname + " " + c.lastname);
WindowAccountOperations LoggedInUser = new WindowAccountOperations();
LoggedInUser.ShowDialog();
return true;
}
else
{
MessageBox.Show("Det finns inte ett sånt användare. Kontrolera användarnamn och pin");
return false;
}
}
return false;
}
//Customer pin could be remade into a rondom generator with an if() that forces it to be a four digit number
/*
* Random randomPin = new Random();
randomPin.Next(x, y);
if(randomPin.ToString().Length!=4)
{
}
*/
public bool CreateNewCustomer(string fornamn, string efternamn, string telefon, string customerAdress, string customerPin)
{
//Is there already such customer?
foreach (Customer c in ListOfAllCustomers)
{
if ((c.firstname == fornamn && c.lastname == efternamn && c.adress == customerAdress))
{
MessageBox.Show("Kunden med ett sånt förnamn, efternamn och adress redan finns");
return false;
}
if(c.pinKod == customerPin)
{
MessageBox.Show("Kunden med ett sånt pinkod redan finns");
return false;
}
else
{
ListOfAllCustomers.Add(new Customer(TBFirstNameNyKund.Text, TBSecondNameLogin.Text, TBTelNyKund.Text, TBAdressNyKund.Text, TBPinNyKund.Text));
MessageBox.Show("Registration complete. Du kan nu logga in");
TBFirstNameNyKund.Clear(); TBSecondNameLogin.Clear(); TBAdressNyKund.Clear(); TBPinNyKund.Clear();//clear login textboxes
return true;
}
}
return false;
}
public bool DoseThisAccountExistAlready(string kontoNummer, string kontotyp)
{
foreach (Customer c in ListOfAllCustomers )
{
foreach(Account a in c.CustomerAccountsList)
{
if(a.accountType==kontotyp)//Does customer c try to create another type of account he already has?
{
return true;
}
if(a.accountNumber==kontoNummer)
{
return true;
}
}
return false;
}
return false;
}
private void ButtonLogin_Click(object sender, RoutedEventArgs e)
{
Login(TBFirstNameLogin.Text, TBSecondNameLogin.Text, TBPinLogin.Text);
}
private void ButtonSkapaKund_Click(object sender, RoutedEventArgs e)
{
CreateNewCustomer(TBFirstNameNyKund.Text, TBSecondNameNyKund.Text, TBTelNyKund.Text, TBAdressNyKund.Text, TBPinNyKund.Text);
}
}
}
//customer class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Uppgift2
{
public class Customer
{
public string adress;
public string celphone;
public string firstname;
public string lastname;
public string pinKod;
public List<Account> CustomerAccountsList = new List<Account>();//Error apears here.
public Customer(string fname,string lname, string tel, string customerAdress,string customerPin)
{
adress = customerAdress;
celphone = tel;
firstname = fname;
lastname = lname;
pinKod = customerPin;
}
}
}
//account base class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Uppgift2
{
abstract class Account //The abstract modifier indicates that the thing being modified has a missing or incomplete implementation=base class for other classes
{
public double payoutAmmount;
protected double payoutTax;
public bool creditPosible;
public string accountNumber;
public string accountType;
public double balance;
protected double interest; //customer shouldent be able to modify interest %
//constructor
public Account(string kontoNummer, double KontoStartsaldo,string kontoTyp, double ranta, bool finsdetkredit,double uttagPris)
{
accountNumber = kontoNummer;
balance = KontoStartsaldo;
accountType = kontoTyp;
creditPosible = finsdetkredit;
payoutTax = uttagPris;
}
public double InsertMoney(int chosenAccount, double payout) //int chosenAccount becouse i thought to use a combo box index
{
payoutAmmount = payout;
balance = balance - payout + (payout * payoutTax);
return balance;
}
}
}
You can't have a public List<Account> because the Account class has no access modifier so it is defaulted by the compiler to be internal. You can't have a public property of an internal type. You need to make it public for this to work.

WCF process-is-terminated-due-to-stackoverflowexception

when i run a method within my WCF service i get "An unhandled exception of type 'System.StackOverflowException' occurred in developer1SVC.dll".
No infinite loops exist and no infinite recursion is occurring. Any ideas to why this may be happening? when i run the method through wcf test client. I get the results back correctly however, hooking it up to my console app and running it breaks the application. The other methods run fine. It is this one method. Just trying to get the feel for WCF services. The service breaks right after i return accounts from the "generateMultiplAccounts" method.
Much help appreciated.
Service
using developer1.Core.ServiceContracts;
using developer1.Core.Data;
using developer1.Core.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using developer1.Core.Dto.Account;
namespace developer1.Core.Service
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
Console.WriteLine(composite.StringValue + composite.BoolValue);
return composite;
}
public List<AccountDto> GenerateMultipleAccounts(int count)
{
List<AccountDto> accounts = new List<AccountDto>();
for (int i = 0; i < count; i++)
{
AccountDto newAccount = new AccountDto() { AccountId = Guid.NewGuid()};
accounts.Add(newAccount);
}
return accounts;
}
}
}
Console Application
using developer1.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using developer1.Core.Service;
using developer1.Core.Dto.Account;
using developer1.Core.ServiceContracts;
using AccountServiceClient = developer1.TestConsole.ServiceReference1.Service1Client;
namespace developer1.TestConsole
{
class Program
{
static void Main(string[] args)
{
try
{
AccountServiceClient AccountServiceClient = new AccountServiceClient();
Guid testGuid = Guid.NewGuid();
List<AccountDto> newAccounts = new List<AccountDto>(AccountServiceClient.GenerateMultipleAccounts(2));
Console.WriteLine(testGuid);
CompositeType testDataContract = new CompositeType() { StringValue = "test", BoolValue = true };
testDataContract = AccountServiceClient.GetDataUsingDataContract(testDataContract);
Console.WriteLine(AccountServiceClient.GetData(6));
Console.WriteLine(testDataContract.StringValue);
//foreach (var item in newAccounts)
//{
// Console.WriteLine(item.AccountId);
//}
}
catch(Exception e) {
Console.WriteLine(e);
}
Console.Read();
}
}
}
Data Contract
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Web;
namespace developer1.Core.Dto.Account
{
[DataContract]
public class AccountDto
{
[DataMember]
public Guid AccountId { get; set; }
//get { return this.AccountId; }
//set { this.AccountId = this.AccountId == Guid.Empty ? Guid.NewGuid() : value; }
[DataMember]
public Guid UserId { get; set; }
[DataMember]
public string AccountName { get; set; }
[DataMember]
public string BankName { get; set; }
//get { return this.BankName; }
//set { this.BankName = this.BankName == null ? "Unspecified" : value; }
}
}
ANSWER!!!!!!!
So I have solved this dreaded issue. You must create a WCF Service Library instead of a WCF Service Application. My god that is stupid that the application wont let you split your components outside of the interface.

C# - In debugger, as soon as execution gets to method, attributes set to 0. Then after, they are back

During defineMapCellPositions() and defineMapCellWalls(), map.cols and map.rows change from values such as 4 and 5 to 0, only for the step through of the methods. A step through the debugger confirms this. Why is this?
Any Help Appreciated, thanks!
Whole Map class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
public class Map
{
public Map()
{
}
public int rows { get; set; }
public int cols { get; set; }
public int boardXPos { get; set; }
public int boardYPos { get; set; }
public int squareSize { get; set; }
private List<List<int>> m_cellPositions = new List<List<int>>();
public List<List<int>> cellPositions
{
get
{
return m_cellPositions;
}
set
{
m_cellPositions = value;
}
}
private List<List<int>> m_cellWalls = new List<List<int>>();
public List<List<int>> cellWalls
{
get
{
return m_cellWalls;
}
set
{
m_cellWalls = value;
}
}
}
Start of MapController Class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
public class MapController
{
public MapController()
{
}
Map map = new Map();
Method to set map.cellWalls
public void defineCellWallsList()
{
//map.cellWalls.Clear();
for (int row = 0; row < (map.rows * map.cols); row++)
{
map.cellWalls.Add(new List<int> { 0, 0 });
}
}
Method to set map.cellPositions
public void defineCellPositionsList()
{
//map.cellPositions.Clear();
for (int row = 0; row < map.rows; row++)
{
for (int col = 0; col < map.cols; col++)
{
map.cellPositions.Add(new List<int> { col, row });
}
}
}
To expose the instance of Map in your MapController either make it a public field, or put it in a property. example:
public class MapController
{
public MapController()
{
}
//here you make it "public" so it is visible to outside classes
public Map map = new Map();
// the rest of your code for this class...
Then to access that instance (assuming you are holding onto an instance of the controller)
var controller = new MapController();
controller.map.rows = 5; // now you can access that instance of map.
controller.map.rows = 123;
Now, to inject the Map into the controller (meaning that it is newed up somewhere else in your code, and the same instance can then be shared accross multiple classes using similar injection procedures) you would do something like this...
public class MapController
{
//here you make it "private" cause it doesn't need to be public anymore,
//you also don't new it up here, you are passing in a new on during construction.
private Map map;
public MapController(Map map)
{
this.map = map
}
// the rest of your code for this class...
Now in the code where you new up the objects and stuff...
var map = new Map();
var controller = new MapController(map);
map.rows = 5; // now you can access that instance of map.
map.rows = 123;
// and you can easily share that same instance with other classes
var otherClass = new SomeOtherClassThatNeedsTheMap(map);

C# asmx web service randomly started redirecting

Monday afternoon I was working on a web service, was able to request the .asmx file in the browser and was given the menu of usable methods and was able to invoke them from the browser with no problems. Tuesday comes around and each time I access it, I get an "Object moved to here" message that links to a nonexistent login.aspx page.
Here's the .asmx.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using System.Data.SqlClient;
namespace LegacyReports
{
/// <summary>
/// Summary description for Example
/// </summary>
[WebService(Namespace = "http://company.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
//[System.Web.Script.Services.ScriptService]
public class Example : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = false)]
public List<ExampleData> ExampleDataSet()
{
Context.Database db = new Context.Database();
String sql = #"SELECT TOP 10 * FROM sometable";
SqlDataReader reader = db.ExecuteReader(sql);
List<ExampleData> data = new List<ExampleData>();
while (reader.Read())
{
int a = Convert.ToInt32(reader["somecolumn"]);
String b = (String)reader["anothercolumn"] + " " + (String)reader["someotherrandomcolumn"];
data.Add(new ExampleData() { a = a, b = b });
}
return data;
}
}
public class ExampleData
{
public int a { get; set; }
public String b { get; set; }
}
}
I'm just not sure why it would work one day then stop the next day. Could it be something with IIS?

WCF client produces error I don't know

I am working on an assignment and I am getting this error which I don't understand. I am writing a WCF client for a working service. Can anyone help me out here?
This line is throwing the error:
MyComplex sumcplx = proxy.complex_sum(one,two);
Error I get
Error: The best overloaded method match for 'NETProxyWCFClient.ProxyTypes.CalculatorClient.complex_sum(NETProxyWCFClient.ProxyTpes.MyComplex,NETProxyWCFClient.ProxyTpes.MyComplex)' has some invalid arguments
Code to my program
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.ServiceModel.Description;
namespace NETProxyWCFClient
{
[DataContract]
public class MyComplex
{
int real;
[DataMember]
public int Real
{
get { return real; }
set { real = value; }
}
[DataMember]
int im;
public int Im
{
get { return im; }
set { im = value; }
}
}
[ServiceContract]
interface ICalculator
{
[OperationContract]
int mult(int a, int b);
[OperationContract]
List<int> fib(int n);
[OperationContract]
MyComplex complex_sum(MyComplex a, MyComplex b);
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter in 2 numbers");
string read = Console.ReadLine();
string[] numbers = read.Split(' ');
int m = int.Parse(numbers[0]);
int n = int.Parse(numbers[1]);
ProxyTypes.CalculatorClient proxy = new ProxyTypes.CalculatorClient();
//Multiplcation
int sum = proxy.mult(m, n);
Console.WriteLine(sum.ToString());
//Mycomplex
MyComplex one = new MyComplex();
one.Im = m;
one.Real = n;
MyComplex two = new MyComplex();
two.Im = n;
two.Real = m;
MyComplex sumcplx = proxy.complex_sum(one,two);
Console.WriteLine(sumcplx.Im + " , " + sumcplx.Real);
//fib one
int[] listM = proxy.fib(m);
foreach (int listItem in listM)
{
Console.Write(listItem.ToString() + " ");
}
Console.WriteLine("");
//fib 2
int[] listN = proxy.fib(n);
foreach (int listItem in listN)
{
Console.Write(listItem.ToString() + " ");
}
Console.ReadLine();
}
}
}
If you have Added a service reference to your test program, there is a proxt class that is generated for you, so if you have ICalculator defined explicity (code you wrote) remove it. it is already in your project, under the NETProxyWCFClient.ProxyTpes.MyComplex,NETProxyWCFClient.ProxyTpes namespace.

Categories