RIA Custom Update method - ria

Given my RIA Service:
[Update]
public void Update(Car car)
{
_carRepository.Update(car);
}
[Update(UsingCustomMethod = true)]
public void UpdateAndClone(Car car)
{
_carRepository.UpdateAndClone(car);
}
How may I "map" SubmitChanges to my Custom update method from my Silverlight client side?
Public void Save(Action<SubmitOperation> submitCallback, object state)
{
_carContext.SubmitChanges(submitCallback, state);
}
Public void SaveAndClone(Action<SubmitOperation> submitCallback, object state)
{
_carContext.SubmitChanges(submitCallback, state);
// _carContext.UpdateAndClone(????)
}
I would like my application to handle the update in two quite different ways according to which action is peformed by the user, but I'm having trouble to understand how my "custom" update should be used.

It seems that I can't have both a "standard" update and a custom update.
So by calling the custom method in the viewmodel before doing .SubmitChanges() solves this issue.

Related

Access SignalR Hub without Constructor Injection

With AspNetCore.SignalR (1.0.0 preview1-final) and AspNetCore.All (2.0.6), how can I invoke a method on a hub in server code that is not directly in a Controller and is in a class that cannot be made via Dependency Injection?
Most examples assume the server code is in a Controller and should 'ask' for the hub via an injectable parameter in a class that will created by DI.
I want to be able to call the hub's method from server code at any time, in code that is not injected. The old SignalR had a GlobalHost that enabled this approach. Basically, I need the hub to be a global singleton.
Now, everything seems to be dependent on using Dependency Injection, which is introducing a dependency that I don't want!
I've seen this request voiced in a number of places, but haven't found a working solution.
Edit
To be more clear, all I need is to be able to later access the hubs that I've registered in the Configure routine of the Startup class:
app.UseSignalR(routes =>
{
routes.MapHub<PublicHubCore>("/public");
routes.MapHub<AnalyzeHubCore>("/analyze");
routes.MapHub<ImportHubCore>("/import");
routes.MapHub<MainHubCore>("/main");
routes.MapHub<FrontDeskHubCore>("/frontdesk");
routes.MapHub<RollCallHubCore>("/rollcall");
// etc.
// etc.
});
If I register them like this:
services.AddSingleton<IPublicHub, PublicHubCore>();
it doesn't work, since I get back an uninitiated Hub.
No It's not possible. See "official" answer from david fowler https://github.com/aspnet/SignalR/issues/1831#issuecomment-378285819
How to inject your hubContext:
Best solution is to inject your hubcontext like IHubContext<TheHubWhichYouNeedThere> hubcontext
into the constructor.
See for more details:
Call SignalR Core Hub method from Controller
Thanks to those who helped with this. Here's what I've ended up on for now...
In my project, I can call something like this from anywhere:
Startup.GetService<IMyHubHelper>().SendOutAlert(2);
To make this work, I have these extra lines in Startup.cs to give me easy access to the dependency injection service provider (unrelated to SignalR):
public static IServiceProvider ServiceProvider { get; private set; }
public static T GetService<T>() { return ServiceProvider.GetRequiredService<T>(); }
public void Configure(IServiceProvider serviceProvider){
ServiceProvider = serviceProvider;
}
The normal SignalR setup calls for:
public void Configure(IApplicationBuilder app){
// merge with existing Configure routine
app.UseSignalR(routes =>
{
routes.MapHub<MyHub>("/myHub");
});
}
I don't want all my code to have to invoke the raw SignalR methods directly so I make a helper class for each. I register that helper in the DI container:
public void ConfigureServices(IServiceCollection services){
services.AddSingleton<IMyHubHelper, MyHubHelper>();
}
Here's how I made the MyHub set of classes:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
public class MyHub : Hub { }
public interface IMyHubHelper
{
void SendOutAlert(int alertNumber);
}
public class MyHubHelper : IMyHubHelper
{
public IHubContext<MyHub> HubContext { get; }
public MyHubHelper(IHubContext<MyHub> hubContext)
{
HubContext = hubContext;
}
public void SendOutAlert(int alertNumber)
{
// do anything you want to do here, this is just an example
var msg = Startup.GetService<IAlertGenerator>(alertNumber)
HubContext.Clients.All.SendAsync("serverAlert", alertNumber, msg);
}
}
This is a nice solution. In .NET Core 2.1 the service provider is disposed and you get cannot access disposed object. The fix is to create a scope:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider.CreateScope().ServiceProvider;

Liferay Service for Business Logics

I want to clear one doubt. I am creating my own service class to manipulate data. Should i create this service instance at class level(in MVCPortlet) or create new instance in my processAction/doView method.
Is there is any issue of thread safety while using instance level.
Fg:
public class MvcCycle extends MVCPortlet {
int counter;
LdapService ldapservice;
#Override
public void init() throws PortletException {
counter=0;
ldapservice = new LdapService(); // Option 1
super.init();
}
#Override
public void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException {
// TODO Auto-generated method stub
System.out.println("Counter hits "+ ++counter);
//
LdapService ldapservice = new LdapService(); // Option 2
ldapservice.authUser(request.getParameter("email"));
// -- some code--
super.doView(renderRequest, renderResponse);
}
#Override
public void destroy() {
System.out.println("Last counter "+counter);
counter=0;
super.destroy();
}
}
class LdapService{
public boolean authUser(String email){
if(//logic to authenticate user){
return true;
}else{
return false;
}
}
}
Here, my ldapservice initiate only once. So when multiple hits come. which code is beneficial on this time either Option1 or Option 2.
Hope i have cleared my problem.
Following up on your comment: in general: it depends. We don't have enough information to give you blank architectural recommendations.
In the context of Liferay it could make sense to utilize service builder, even if you don't have database interaction. Just create an empty entity, you'll have a service with no persistence.
<entity name="MyService" local="true"/>
That's it. Now implement MyServiceLocalServiceImpl added you're done
Edit, after your clarification: it doesn't make a difference. I'd still recommend to not instantiate at all in your portlet, because that makes your portlet dependent on the service implementation. E.g. I still go with service builder.
You're also asking about thread safety and that depends on your implementation as well. Your sample code is thread safe, but the actual code might not be. Your judgement.

OutputCache and injected ActionParameters

We use a ActionFilterAttribute to inject some parameters into actions and it works great.
But when we add OutputCache it varies exclusively on "MyID" when Html.RenderAction() is used and not when surfing directly to the action.
Any ideas how to get OutputCache to always recognize "MyID"?
Controller
[SiteIDs, OutputCache]
public ActionResult SiteContent(string myID)
{
return Content(myID);
}
ActionFilter
public class SiteIDs : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.ActionParameters.ContainsKey("MyID"))
{
filterContext.ActionParameters["MyID"] = GetMyIDByHostname();
}
base.OnActionExecuting(filterContext);
}
}
With the OutputCacheAttribute, action filters will not execute when a page is retrieved from the cache. You should probably use mvcdonutcaching in order to have the action filters executed even when retrieving from the cache. I'd recommend reading this.
Option 1
According to this answer, you just need to use VaryByParam = "*" and it will automatically vary by the parameters you pass the action method.
[SiteIDs, OutputCache(VaryByParam = "*")]
public ActionResult SiteContent(string myID)
{
return Content(myID);
}
However, that may not work by using an IActionFilter (haven't tried it). You might try using an IValueProvider instead (which is a cleaner way to do what you are doing with the action filter, anyway).
Option 2
You could use VaryByCustom and GetVaryByCustomString to vary the cache by hostname.
[SiteIDs, OutputCache(VaryByParam = "none", VaryByCustom = "hostname")]
public ActionResult SiteContent(string myID)
{
return Content(myID);
}
And in your Global.asax file:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
public override string GetVaryByCustomString(HttpContext context, string custom)
{
if (custom == "hostname")
{
return "HostName=" + context.Request.Url.Host;
}
return base.GetVaryByCustomString(context, custom);
}
}
Keep in mind your action filter will only be hit if the OutputCache has not been set. So you need to vary the cache on the same value (or values) that you vary your ID from. The simplest solution is to use something that is already in HttpContext, such as host name.

Using Catel with Repository Pattern, EF6 and View Models

I cannot find any documentation on connecting a view model to a repository using Catel.
I have set up the Repository Pattern and my Models with EF6 Code First (all extending from ModelBase) but need to know how to use it with a ViewModel.
Do I need to create a service for the UnitOfWork? And if so, how? How will I use this in a ViewModel?
I am currently using the repository as a model in my viewmodel, but i do not think this is the correct way to do it? See my CompaniesViewModel below:
IUnitOfWork uow;
public CompaniesViewModel()
{
uow = new UnitOfWork<SoftwareSolutionsContext>();
CompanyRepository = uow.GetRepository<ICompanyRepository>();
}
public override string Title { get { return "Companies"; } }
protected override async Task Close()
{
uow.Dispose();
await base.Close();
}
protected override async Task Initialize()
{
Companies = new ObservableCollection<Company>(CompanyRepository.GetAll());
await base.Initialize();
}
public ObservableCollection<Company> Companies
{
get { return GetValue<ObservableCollection<Company>>(CompaniesProperty); }
set { SetValue(CompaniesProperty, value); }
}
public static readonly PropertyData CompaniesProperty = RegisterProperty("Companies", typeof(ObservableCollection<Company>), null);
[Model]
public ICompanyRepository CompanyRepository
{
get { return GetValue<ICompanyRepository>(CompanyRepositoryProperty); }
private set { SetValue(CompanyRepositoryProperty, value); }
}
public static readonly PropertyData CompanyRepositoryProperty = RegisterProperty("CompanyRepository", typeof(ICompanyRepository));
Essentially, I have 2 scenarios for working on the data:
getting all the data to display on a datagrid
selecting a record on the datagrid to open another view for editing a single record
Any guidance would be appreciated.
This is a very difficult subject, because there are basically a few options here:
Create abstractions in services (so the VM's only work with services, the services are your API into the db). The services work with the UoW
There are some people thinking that 1 is overcomplicated. In that case, you can simply use the UoW inside your VM's
Both have their pros and cons, just pick what you believe in most.

MVC5/API2 CreateErrorResponse in custom ActionFilterAttribute OnActionExecuting

With MVC4 I was able to create and register a global action filter that would check the model state prior to the action's execution and return the serialized ModelState before any damage could be done.
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
However, with MVC5, I am having trouble finding Request and therefore CreateErrorResponse
public override void OnActionExecuting(ActionExecutingContext nActionExecutingContext)
{
if (!nActionExecutingContext.Controller.ViewData.ModelState.IsValid)
{
nActionExecutingContext.Result = // Where is Request.CreateErrorResponse ?
}
}
I realize that I could create a custom response class to assign to Result but I'd rather use what's built-in if CreateErrorResponse is still available.
Any idea where I can find it relative to an ActionExecutingContext in MVC5 / Web API 2?
I know this is an old question but I recently had the same problem and solved it using
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(context.ModelState);
}
}

Resources