wcf data service binding combobox - wcf

I have an application with silvelight and wcf data services.
I want to populate comboBox with value of my column 'City'
Can someone give me the correct way to do this, because my function failed with System.InvalidOperationException !
public void GetCities(System.Windows.Controls.ComboBox cmbCity)
{
DataServiceQuery<String> userQuery = (DataServiceQuery<String>)proxy.CreateQuery<String>("GetCity");
try
{
userQuery.BeginExecute(
(result) =>
{
var userlist = new DataServiceCollection<string>(userQuery.EndExecute(result));
cmbCity.ItemsSource = userlist.ToList();
}, null);
}
catch (DataServiceQueryException ex)
{
throw ex;
}
}
In my WCF Data Service, :
[WebGet]
public IQueryable<String> GetCity()
{
return Usager.GetCity();
}
in my edmx project, I have this:
public static IQueryable<String> GetCity()
{
try
{
DataBaseEntities scv = new DataBaseEntities();
return (from user in scv.Usager
select user.City).Distinct();
}
catch (Exception ex)
{
throw ex;
}
}

Related

Unable to read FaultException from an asp.net core connected service

I'm trying to catch the FaultException on a WCF client.
the generated reference contract is:
[System.ServiceModel.OperationContractAttribute(Action="urn:wcfname#method", ReplyAction="*")]
[System.ServiceModel.FaultContractAttribute(typeof(Error[]), Action= "urn:wcfname#method", Name="errors")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(Response))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(Request))]
service.response method(service.request request);
and the generated error class is:
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.2")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="wcf")]
public partial class Error
{
private string errorCodeField;
private string errorStringField;
private string subErrorCodeField;
private string offendingFieldField;
private System.DateTime timeStampField;
private bool timeStampFieldSpecified;
private string detailStringField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="integer", Order=0)]
public string errorCode
{
get
{
return this.errorCodeField;
}
set
{
this.errorCodeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=1)]
public string errorString
{
get
{
return this.errorStringField;
}
set
{
this.errorStringField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(DataType="integer", Order=2)]
public string subErrorCode
{
get
{
return this.subErrorCodeField;
}
set
{
this.subErrorCodeField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public string offendingField
{
get
{
return this.offendingFieldField;
}
set
{
this.offendingFieldField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=4)]
public System.DateTime timeStamp
{
get
{
return this.timeStampField;
}
set
{
this.timeStampField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool timeStampSpecified
{
get
{
return this.timeStampFieldSpecified;
}
set
{
this.timeStampFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=5)]
public string detailString
{
get
{
return this.detailStringField;
}
set
{
this.detailStringField = value;
}
}
}
the code to call the sercie is below:
try
{
//call the service method
}
catch (FaultException<Error[]> ex)
{
var errorElement = XElement.Parse(ex.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml());
var xmlDetail = (string)errorElement;
}
catch (FaultException ex)
{
var errorElement = XElement.Parse(ex.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml());
var xmlDetail = (string)errorElement;
}
When theres a FaultExeption<Error[]> ex, it enters there, but the error is empty string.
If I comment that part, it enters on the FaultException ex, but again the error is empty string.
I'm using .netCore 3.1
Any advice is appreciated.
Throwing FaultException indicates that there is no problem with the channel. The exception was thrown by the service. WCF's FaultException message is too general to pinpoint a specific problem, so you can customize the exception message like this:
public class HomeService : IHomeService
{
public Student Get(string id)
{
try
{
//Here, of course, an exception will be thrown
var result = Convert.ToInt32(id) / Convert.ToInt32("0");
return new Student() { ID = Convert.ToInt32(id), Name = "hxc", SNS = "001" };
}
catch (Exception ex)
{
var reason = new FaultReason("Exception thrown information");
var code = new FaultCode("500");
var faultException = new FaultException(reason, code, "It is GET that throws the exception");
throw faultException;
}
}
}

RedirectToAction with parameters in the path

I'm trying to use RedirectToAction to redirect to one of the three actions below. However RedirectToAction is redirecting to /Move/Staging?userId=12345 which results in a 404. What I'm trying to do with the RedirectToAction is that it redirects to /Move/12345/Staging.
I'm using RedirectToAction as follows
return RedirectToAction("StagingMove", "Maintenance", new { userId = model.userId});
I've configured the Actions as followed.
[HttpGet("Move/{userId?}/Staging/")]
public async Task<IActionResult> StagingMove(string userId)
{
try
{
{Snip}
return View(user );
}
catch (Exception ex)
{
this._logger.LogError(0, ex, "Move User Staging");
throw ex;
}
}
[HttpGet("Move/{userId?}/Arrival/")]
public async Task<IActionResult> StagingArrival(string userId)
{
try
{
ApplicationUser user = await this._userManager.GetUserAsync(userId);
return View(user );
}
catch (Exception ex)
{
this._logger.LogError(0, ex, "Move User Arrival");
throw ex;
}
}
[HttpGet("Move/{userId?}/Departures/")]
public async Task<IActionResult> StagingDepartures(string userId)
{
try
{
ApplicationUser user = await this._userManager.GetUserAsync(userId);
return View(user );
}
catch (Exception ex)
{
this._logger.LogError(0, ex, "Move User Departures");
throw ex;
}
}
I've looked into this and as far as I can tell it does work for when you have Move/Staging/{userId}. However, I can't get it to work in my situation with stuff behind the parameter.
Thanks to #King-king I got it working.
attribute routing and convention-based routing are exclusively
effective. In this case you use attribute routing so the path used in RedirectToAction won't work.
I modified my actions, for example:
[Route("Move/{userId?}/Staging/", Name = "MoveStaging")]
public async Task<IActionResult> StagingMove(string userId)
{
try
{
{Snip}
return View(user );
}
catch (Exception ex)
{
this._logger.LogError(0, ex, "Move User Staging");
throw ex;
}
}
Now I can use RedirectToRoute.
return RedirectToRoute("MoveStaging", new { userId = model.userId});

Unable to access the delete endpoint in asp.net core webapi

I have .net core web api and able to access the get endpoint but not the delete. How do i access the delete endpoint. I am not sure what the problem is ?
I have tried the following
http://localhost:53538/api/cities/delete-city/1
I have been using for the get endpoint.
http://localhost:53538/api/cities
controller
public class CitiesController : Controller
{
private readonly ICityInfoService _cityInfoService;
public CitiesController(ICityInfoService cityInfoService)
{
_cityInfoService = cityInfoService;
}
[HttpGet]
public IActionResult GetCities()
{
var cities = _cityInfoService.GetCities();
if (!cities.Any())
return NoContent();
var citiesMapped = cities.Select(MapCity);
return Ok(citiesMapped);
}
[HttpGet("{cityId:int}")]
public IActionResult GetCity(int cityId)
{
try
{
var city = _cityInfoService.GetCity(cityId);
var cityMapped = MapCity(city);
return Ok(cityMapped);
}
catch (CityNotFoundException e)
{
return BadRequest(e.Message);
}
catch (Exception ex)
{
return StatusCode(500, ex.Message);
}
}
[HttpDelete("delete-city/{cityId:int}")]
public IActionResult DeleteCity(int cityId)
{
try
{
_cityInfoService.DeleteCity(cityId);
return Ok();
}
catch (CityNotFoundException e)
{
return BadRequest(e.Message);
}
catch (Exception ex)
{
return StatusCode(500, ex.Message);
}
}
private static CityDto MapCity(City city)
{
return new CityDto
{
Id = city.Id,
Description = city.Description,
Name = city.Name
};
}
}
Your delete method is a HttpDelete, so it needs DELETE request. If you a trying to hit the endpoint via a browser, it won't work as it will just do a GET.
You can use Curl or Postman to issue the DELETE request to your URL.

How do I return an InternalErrorResult?

I am using Swagger with a .Net Core API.
When there is a bug in the API I want to receive an InternalServerError
However there is no NotOK method to do this.
Currently I have the following in my base controller
using System;
using Microsoft.AspNetCore.Mvc;
namespace MyApi.Controllers
{
public class BaseController : Controller
{
public IActionResult RouteInterfaceMethod<TResponse>(Func<TResponse> function)
{
// try
// {
IActionResult res = null;
TResponse ret = function();
res = Ok(ret);
return res;
// }
// catch (Exception e)
// {
// var msg = MakeErrorMessage(e);
// return base.NotFound( msg);
// }
}
}
}
And am about to un-comment the code ,is there an alternative to using NotFound()
You can return InternalServerError in this way
catch (Exception e)
{
var msg = MakeErrorMessage(e);
return StatusCode(HttpStatusCode.InternalServerError, msg);
}
or just re-throw an exception
catch (Exception e)
{
var msg = MakeErrorMessage(e);
throw;
}

NHibernate Repository pattern problem

I am using NHibernate and Repository patterns in my application. But not want to use UnitofWork pattern.
There are two types of forms in my app. Collection/Picker forms and Entity forms.
But the problem occurs when a form is ShowDialog()ged from within another form.
Whwn I am doing any database related operation, NHibernate is giving me "a different object with the same identifier value was already associated with the session: XYZ" error. This is caused due to the delayed call of Dispose method by CLR and another part of my problem is in the Session management as far as I guess.
How can I change my repository codes to solve my problem?
Remember, I don't want to expose separate BeginTransaction(), CommitTransaction() like functions in my Repository. These things should be embedded within every Method {SaveOrUpdate(), Save(), Delete, Load(), etc.} as I have already done.
Please tell me how can I get things going with minor changes?
I am doing my things like this:
A picker form works like this,
private void btnPick_Click(object sender, EventArgs e)
{
CourseCollectionForm f = new CourseCollectionForm();
f.FormViewMode = FormViewMode.MultiplePicker;
f.ShowDialog();
int totalCredits = 0;
int totalHours = 0;
FillDataGridViewWithCourses(f.PickedCourseCollection, ref totalCredits, ref totalHours);
FillTotal(totalCredits, totalHours);
}
A Save works like this,
public partial class DepartmentEntityForm : Form
{
private DepartmentRepository _deptRepository = null;
private Department _currentDepartment = null;
private FormViewMode _currentMode = FormViewMode.None;
public DepartmentEntityForm(Department dept, FormViewMode mode)
{
InitializeComponent();
_deptRepository = new DepartmentRepository();
_currentDepartment = dept;
_currentMode = mode;
if(mode == FormViewMode.Edit)
{
MapObjectToControls();
}
}
private void SaveButton_Click(object sender, EventArgs e)
{
Department newDept;
if (mode == FormViewMode.AddNew)
{
newDept = new Department();
}
else if(mode == FormViewMode.Edit)
{
newDept = _currentDepartment;
}
//.............
//.............
_deptRepository.SaveOrUpdate(newDept);
}
}
I declare my individual repositories like this:
FacultyRepository.cs
public class FacultyRepository : Repository<Faculty>
{
}
DepartmentRepository.cs
public class DepartmentRepository : Repository<Department>
{
}
Repository.cs
public class Repository<T> : IRepository<T>
{
ISession _session;
public Repository()
{
_session = SessionFactory.GetOpenSession();
}
public T Get(object id)
{
T obj = default(T);
try
{
if (!_session.Transaction.IsActive)
{
_session.BeginTransaction();
obj = (T)_session.Get<T>(id);
_session.Transaction.Commit();
_session.Flush();
}
else
{
throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
}
}
catch (Exception ex)
{
_session.Transaction.Rollback();
_session.Clear();
throw ex;
}
return obj;
}
public IEnumerable<T> Get(string fieldName, object fieldValue)
{
IEnumerable<T> list = null;
try
{
if (!_session.Transaction.IsActive)
{
_session.BeginTransaction();
list = (IEnumerable<T>)_session.CreateCriteria(typeof(T))
.Add(new NHibernate.Expression.EqExpression(fieldName, fieldValue))
.List<T>();
_session.Transaction.Commit();
_session.Flush();
}
else
{
throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
}
}
catch (Exception ex)
{
_session.Transaction.Rollback();
_session.Clear();
throw ex;
}
return list;
}
public IEnumerable<T> Get()
{
IEnumerable<T> list = null;
try
{
if (!_session.Transaction.IsActive)
{
_session.BeginTransaction();
list = (IEnumerable<T>)_session.CreateCriteria(typeof(T)).List<T>();
_session.Transaction.Commit();
_session.Flush();
}
else
{
throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
}
}
catch (Exception ex)
{
_session.Transaction.Rollback();
_session.Clear();
throw ex;
}
return list;
}
public void SaveOrUpdate(T obj)
{
try
{
if (!_session.Transaction.IsActive)
{
_session.BeginTransaction();
_session.SaveOrUpdateCopy(obj);
_session.Transaction.Commit();
_session.Flush();
}
else
{
throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
}
}
catch (Exception ex)
{
_session.Transaction.Rollback();
_session.Clear();
throw ex;
}
}
public void SaveOrUpdate(IEnumerable<T> objs)
{
try
{
if (!_session.Transaction.IsActive)
{
_session.BeginTransaction();
foreach (T obj in objs)
{
_session.SaveOrUpdate(obj);
}
_session.Transaction.Commit();
_session.Flush();
}
else
{
throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
}
}
catch (Exception ex)
{
_session.Transaction.Rollback();
_session.Clear();
throw ex;
}
}
public void Delete(T obj)
{
try
{
if (!_session.Transaction.IsActive)
{
_session.BeginTransaction();
_session.Delete(obj);
_session.Transaction.Commit();
_session.Flush();
}
else
{
throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
}
}
catch (Exception ex)
{
_session.Transaction.Rollback();
_session.Clear();
throw ex;
}
}
public void Delete(IEnumerable<T> objs)
{
try
{
if (!_session.Transaction.IsActive)
{
_session.BeginTransaction();
foreach (T obj in objs)
{
_session.Delete(obj);
}
_session.Transaction.Commit();
_session.Flush();
}
else
{
throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
}
}
catch (Exception ex)
{
_session.Transaction.Rollback();
_session.Clear();
throw ex;
}
}
public void DeleteAll()
{
try
{
if (!_session.Transaction.IsActive)
{
_session.BeginTransaction();
DetachedCriteria criterion = DetachedCriteria.For<T>();
IList<T> list = criterion.GetExecutableCriteria(_session).List<T>();
foreach (T item in list)
{
_session.Delete(item);
}
_session.Transaction.Commit();
_session.Flush();
}
else
{
throw new Exception(CustomErrorMessage.TransactionAlreadyInProgress);
}
}
catch (Exception ex)
{
_session.Transaction.Rollback();
throw ex;
}
}
public void Dispose()
{
if (_session != null)
{
_session.Clear();
_session.Close();
_session = null;
}
}
}
SessionFactory.cs
public class SessionFactory
{
private static ISessionFactory _sessionFactory = null;
private SessionFactory(){}
static SessionFactory()
{
if (_sessionFactory == null)
{
Configuration configuration = new Configuration();
configuration.Configure();
_sessionFactory = configuration.BuildSessionFactory();
}
}
public static ISession GetOpenSession()
{
return _sessionFactory.OpenSession();
}
}
OK guys! It has been long since I posted my question and nobody tends to answer it.
I solved it by making ISession static in the SessionFactory and instead of returning a Open ISession for each Repository, I am returning only one static ISession.