I made some changes to my interface for a RIA service, but SL is not getting them when I do an update.
Basically changed a few from void to bool so I could check for completion.
I've tried deleting, getting again, etc.
No matter what I do, when I call my client side context it still shows the old interface.
[ServiceContract]
public interface IUploadService
{
[OperationContract]
bool UploadFile(CrmFileUpload fileUpload);
}
public partial class CrmFileUpload
{
public string FileName { get; set; }
public byte[] Chunk { get; set; }
}
Updated code:
public void TestMe(string testString)
{
_context.TestMethodAsync(testString); //this shows void, but everything in the WCF is a string
}
Related
I'm new to working with WCF and i'm struggling to understand whats happening.
I'm trying to retrieve data from my service, which in turn grabs it from the database. To simplify things I wanted to return an object containing the data so that it could just be used immediatly within the UWP app. However, I'm running into the following error when I try to consume the service:
Cannot implicitly convert type 'MBCMobile.ServiceReference1.TaskBreakdown_GetDataResponse' to 'MBCMobile.ServiceReference1.JobTestObject'
The following code is what I'm using:
[ServiceContract]
public interface IService1
{
[OperationContract]
JobTestObject TaskBreakdown_GetData(int task, int appliance, int job);
}
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class Service1 : IService1
{
public JobTestObject TaskBreakdown_GetData(int task, int appliance, int job)
{
JobTestObject jobData = data.TaskBreakdown_GetData(task, appliance, job); //object returned from sql query
return jobData;
}
}
To consume my service im using the following:
private async void GetString()
{
ServiceReference1.Service1Client service = new ServiceReference1.Service1Client();
JobTestObject datalist = await service.TaskBreakdown_GetDataAsync(6153, 18876, 18111);
}
JobTestObject has the same format in both the service and the UWP app. The service version literally exists as a collection of get/set methods and nothing else. The app version has additional methods, but the exact same get/set methods. I've tried using ServiceReference1.JobTestObject instead to see if that helps but to no avail. I expect that it might be a little naive of me to think an object can be passed to the client this way.
I also tried just returning a list of strings and got a similar error.
I've managed fine in the past with retrieving single values from the service, but now that I want to get multiple values at once I can't understand what I'm doing wrong. Sadly most of the solutions I've found don't relate to UWP apps
Update: As requested
[DataContract]
public class JobTestObject
{
int appliance_id, manu_id, model_id, landlord_app, applianceType_id,
[DataMember]
public int ApplianceType { get { return applianceType_id; } set { applianceType_id = value; } }
[DataMember]
public int Appliance_ID { get { return appliance_id; } set { appliance_id = value; } }
[DataMember]
public int ApplianceManufacturer { get { return manu_id; } set { manu_id = value; } }
[DataMember]
public int ApplianceModel { get { return model_id; } set { model_id = value; } }
}
I need plan for build Notifications/Alerts system.
I have object named "Campaign" and it have "Status". Status can be Accepted, Rejected, Supplement, Work and others.
I want send Notifications/Alerts when the Status change.
E.q. e-mail notification and alert in my portal.
I don't want make it all in one controller where I operate on Campaign. So I was thinking about Delegates and Events. But in last I don't know enought to do it.
What I thinking about:
Domain model:
class Campaign {
CampaignStatus Status { get; set;}
}
abstract class Notification {
// properties
}
class EmailNotification {
// properties specific for email
}
class Alert {
// properties specific for alerts
}
class CampaignAlert {
// properties specific for campaign alerts
}
Services:
INotificationsService {
Send();
}
IAlertsService : INotificationsService {
Get(); // I need showing list of alerts too
GetAll();
Update(); // for updating info if alert was viewed.
Save(); // I need saving alerts in db.
}
And how I can do it with events? So much automatic as can. Ofcourse I can manualy call the AlertsService and make alert. But this is bad ;)
I was thinking about adding delegate and event to Campaign.
class Campaign {
public delegate void CampaignStatusChange(object sender, EventArgs e);
public event CampaignStatusChange OnCampaignStatusChange;
}
And connect event with:
class CampaignStatusChangeHandler {
public CampaignStatusChangeHandler(IRepository<bla bla> repository, INotificationsService notificationService) {
// these will be inject via ctor
}
//
}
I want made it as much as I can with SOLID, KISS, and DRY. Ofcourse with TDD and I using IoC to inject objects ;)
Summary I need notification service that I can indepentend send emails and alerts. I need display alerts on frontend.
My alert domain model like that:
public abstract class Notification
{
public string Title { get; set; }
public string Content { get; set; }
public DateTime Created { get; set; }
public NotificationType Type { get; set; }
}
public enum NotificationType
{
Email,
Alert
}
public class EmailNotification : Notification
{
public string From { get; set; }
public ICollection<string> To { get; set; }
public ICollection<string> Bcc { get; set; }
}
public class Alert : Notification
{
public object LinkedObject { get; set; }
public bool WasSeen { get; set; }
}
public class CampaignAlert : Alert
{
public CampaignAlertType CampaignAlertType { get; set; }
}
public enum CampaignAlertType
{
Accepted,
Rejected,
Active,
Finished
}
When I want to send Alert to user I want send email sometimes and alert.
Sometimes I want send only email and only alert.
I wouldn't use delegates and events here. Calling a method is much more transparent and you wouldn't have any benefits of using delegates and events.
My structure would look like that:
interface ICampaignService
{
// It's business logic
// 1. Updates campaign
// 2. Creates notification using builder
// 3. Uses notification sender to send notification
// (4. creates alert object for notification)
void UpdateCampaignStatus(int campaignId, Status status);
}
// Builds different notifications based on different
// campaign statuses. For instance assign different
// email templates and use different text.
interface INotificationBuilder<TNotification> where TNotification : Notification
{
TNotification Build();
}
interface INotificationSender
{
Send(Notification notification);
}
interface IAlertsRepository
{
Get();
GetAll();
Update();
Create();
}
Also possible (if there are different types of notifications)
// If you want to send different types of notifications like
// Email, Push, SMS etc. Each notification type requires different
// logic for sending notification. Strategy pattern is perfect here.
interface INotificationStrategy : INotificationSender
{
Send(Notification notification);
}
It's all depends on your application extensibility requirements. SOLID is very important, but make sure to avoid over-engineering (you mentioned KISS :)).
I have a Prototype using WPF + MVVM + PRISM + ENTITY FRAMEWORK
The problem is that im very confuse if i use the ENTITY FRAMEWORK Entities as the Model of the MVVM pattern. I have a Business Logic Layer, and i had problems using mappers on this layer, because im very unhappy on the conversion (Map problem).
What i can do to simplify the code, use a real Model not the Entitie object(for me use the Entitie as model is incorrect on the frontend), with the MVVM pattern on mind... and stay good for changes on the future, it will have 200+ entities on the final version...
Thats my layers...(Please forget about Mapping, since i taked it off putting the EF entities on the ViewModel, but the image represents the correct layers)
Im not using the repository too since i can add it on the end with changes only on the BLL.
VIEW MODEL:
my current prototype do a getall, put it on a grid, and on selectchanged of the grid i put selected item on the textbox, and the save button update this changes to the database.
public class CadastroClienteViewModel : BindableBase, ICadastroClienteViewModel
{
private readonly IClienteBLL _clienteService;
#region Model
//public Cliente ObCliente { get; private set; }
public int ClienteID
{
get { return ((Cliente)cliItems.CurrentItem).ClienteID; }
set
{
((Cliente)cliItems.CurrentItem).ClienteID = value;
OnPropertyChanged("ClienteID");
}
}
public string Nome
{
get { return ((Cliente)cliItems.CurrentItem).Nome; }
set
{
((Cliente)cliItems.CurrentItem).Nome = value;
OnPropertyChanged("Nome");
}
}
#endregion
public CadastroClienteViewModel(IClienteBLL ServiceCliente)
{
//ObCliente = new Cliente();
_clienteService = ServiceCliente;
this.SaveCommand = new DelegateCommand(ExecuteMethodSave);
this.RefreshCommand = new DelegateCommand(ExecuteMethodRefresh, CanExecuteMethodRefresh);
RefreshCommand.Execute(null);
}
private void ExecuteMethodSave()
{
_clienteService.ClienteBLL_Update(((Cliente)cliItems.CurrentItem));
RefreshCommand.Execute(null);
}
private bool CanExecuteMethodRefresh()
{
return true;
}
private void ExecuteMethodRefresh()
{
var personViewModels = _clienteService.ClienteBLL_GetAll();
//cliente = new ObservableCollection<Cliente>(personViewModels);
cliItems = new ListCollectionView(personViewModels.ToList());
cliItems.CurrentChanged += CliItemsOnCurrentChanged;
//OnPropertyChanged("cliente");
OnPropertyChanged("cliItems");
}
private void CliItemsOnCurrentChanged(object sender, EventArgs eventArgs)
{
//OnPropertyChanged("ObCliente");
}
public ICommand SaveCommand { get; private set; }
public ICommand RefreshCommand { get; private set; }
//public ObservableCollection<Cliente> cliente { get; private set; }
public ICollectionView cliItems { get; private set; }
}
MODEL(Im not using it... but i would like):
public class MCliente
{
public int ClienteID { get; set; }
public string Nome { get; set; }
}
EF Entitie:
namespace Sistema.DataEntities.Models
{
public class Cliente
{
public Cliente()
{
}
public int ClienteID { get; set; }
public string Nome { get; set; }
}
BLL:
public class ClienteBLL : IClienteBLL
{
readonly ISistemaContext _context;
public ClienteBLL(ISistemaContext context)
{
_context = context;
}
public IEnumerable<Cliente> ClienteBLL_GetAll()
{
return _context.Cliente.AsEnumerable();
}
public Cliente ClienteBLL_GetByID(int id)
{
return _context.Cliente.Find(id);
}
public bool ClienteBLL_Adicionar(Cliente Obcliente)
{
_context.Cliente.Add(Obcliente);
return _context.SaveChanges() > 0;
}
public bool ClienteBLL_Update(Cliente Obcliente)
{
_context.Cliente.Attach(Obcliente);
_context.Entry(Obcliente).State = EntityState.Modified;
return _context.SaveChanges() > 0;
}
public bool ClienteBLL_Delete(int id)
{
var clubMember = _context.Cliente.Find(id);
_context.Cliente.Remove(clubMember);
return _context.SaveChanges() > 0;
}
I'm adding this as an answer (not a comment) even if it's not a final answer to your question (cause it's opinion-based) but it doesn't fit as a comment. That's just what I would do for a WPF application that requires a database.
I would entirely drop the idea of directly connecting your WPF application to your database. I would build a 3-tiers architecture, i.e. I would create a stateless webservice that does all the stuff on server side.
So you would have:
the database
the webservice (using WCF), that is connected to the database, that does all the data stuff for you (I would even make it responsible of the business stuff too)
the WPF application, that is connected to the webservice:
the View layer is your XAML + your code-behind
the ViewModel layer is, well, your ViewModels (out of scope of your question, but feel free to ask if you have any question about that layer). The ViewModels asynchronously call the webservice
the Model is the client WCF proxy
Some benefits of this approach:
depending on the hardware/network harchitecture, could be a huge performance benefit to only make ONE call to the server instead of N calls (assuming the latency between the DB and the webservice (both on "server side") is lower than the one between the WPF application and the database)
more scalable
all benefits of the stateless approach: one Entity Framework context instantiation per webservice requests, so much easier to deal with concurrency issues (in case you have N WPF instances running concurrently)
easier to maintain (loose coupling between tiers)
easier to test (assuming you actually build tests)
better security (no need to expose a direct access to the database over the network)
I have a WCf service with Contracts shown below.
[MessageContract]
public class ServiceRequest
{
[MessageBodyMember]
public int RequestId { get; set; }
[MessageBodyMember]
public OrderDetails OrderDetails { get; set; }
}
[DataContract]
public class OrderDetails
{
[IsLogRequired]
public int OrderId { get; set; }
[IsLogRequired]
public int Quantity { get; set; }
public string CustomerName { get; set; }
}
[IsLogRequired] is custom Attribute.
We need to get all properties in the request which have "[IsLogRequired]" attribute when the request is received. We want to do it as generic solution so that it can be plugged into all services.
We thought of using "MessageInspector" to do this implementing "IDispatchMessageInspector".
How do i get the actual request object from "System.ServiceModel.Channels.Message" parameter of IDispatchMessageInspector.AfterReceiveRequest() method?
Please correct me if i am using a wrong interface or wrong method. Any other solution to this?
I am assuming that "[IsLogRequired] is custom property." means a custom attribute...
Simple answer is that there is no solution to transfer custom attributes that are decorating the data contract as you described it.
Data contracts should be pure and not encumbered by business logic. The know how about the what should be done with various fields belongs to a service implementation.
Possible approach could look like this:
public class OrderService : IOrderService
{
private void ProcessOrder(Order order)
{
var ra = new AuditMetadataResourceAccess();
MethodInfo[] fieldsToLog = ra.GetLoggingFields(typeof(OrderDetal));
if (fieldsToLog.Any())
{
var logger = new LogingEngine();
logger.Log(fieldsToLog, order.OrderDetails);
}
}
}
You could move this implementation inside message inspector or operation invoker. Carlos Figueira has extensive description of each WCF extensibility point.
"How do i get the actual request object from "System.ServiceModel.Channels.Message" parameter of IDispatchMessageInspector.AfterReceiveRequest() method?"
I am assuming you are referring to Web request. WebOperationContext.Current but you need to have ASP.NET Compatibility Mode turned on.
I have a WCF service that passes back and forth the following DataContracts:
[DataContract]
public class RequestWrapper
{
[DataMember]
public FooDataContract FooDataContract;
}
[DataContract]
public class ResponseWrapper
{
[DataMember]
public FooDataContract FooDataContract;
}
[DataContract]
public class FooDataContract
{
public FooDataContract(string data, Guid id)
{
Data = data;
ID = id;
}
[DataMember]
public string Data { get; set; }
[DataMember]
public Guid ID { get; set; }
}
It's called via a proxy class like this:
void CallService(string data)
{
var id = Guid.NewGuid();
var response = proxy.CallService(new RequestWrapper
{
new FooDataContract(data, id);
});
}
This is then passed (over the service) to the database via a repository using EF:
public void RepoMethod(FooDataContract foo)
{
var guid = foo.ID; // - Breakpoint here shows all zeros!
efContext.DoSomething(foo.Data, foo.ID);
}
Here's the service call:
public ResponseWrapper CallService(RequestWrapper request)
{
var foo = request.FooDataContract;
repository.RepoMethod(foo);
var response = new ResponseWrapper{ FooDataContract = foo };
return response;
}
Here's the proxy:
public class Proxy : IMyService
{
static readonly ChannelFactory<IMyService> channelFactory =
new ChannelFactory<IMyService>("IMyService");
ResponseWrapper CallService(RequestWrapper request)
{
return channelFactory.UseService(s => s.CallService(request));
}
}
internal static class UseServiceFunction
{
internal static R UseService<T, R>
(this ChannelFactory<T> channelFactory, Func<T, R> useService)
{
var service = channelFactory.CreateChannel();
try
{
R response = useService(service);
return response;
}
finally
{
var channel = service as ICommunicationObject;
try
{
if (channel.State != CommunicationState.Faulted) channel.Close();
}
catch { channel.Abort(); }
}
}
}
I've put a watch on the Guid in the VS debugger. When the service is called from a client web application, the generated Guid is a valid Guid of seemingly random hex characters. Great, that's working.
But when the data is serialized, goes over the wire, and comes out the other side (in my repository), the Guid is all zeros!
I've double, triple checked that the Guid is indeed marked with the [DataMember] attribute. I'm wondering if the extra layer of DataContract (how a FooDataContract is wrapped with the RequestWrapper data contract) is causing a serialization issue?
I think your problem here is that the constructor you've made in your DataContract class doesn't get passed to the proxy on the client side. WSDL won't know anything about this. Think of your data contracts as just a place to stick data with no other functionality. To confirm, you can look in the reference.cs class that got generated in the client when you added the service reference.
I'd suggest re-writing the code so that you explicitly set each of the values in your data contract rather than relying on the constructor.
You can also write a hand coded proxy that has whatever behavior you want and then share that file with the client. That would work, but then you'll be more tightly coupling your client to your service.
Turns out, my translation layer wasn't updated to convert between the DTOs! Whooooops!