I'm using Unity to inject a context and using the following lifetime manager...
public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable
{
#region IDisposable Members
public void Dispose()
{
RemoveValue();
}
#endregion
public override object GetValue()
{
object value = HttpContext.Current.Items[typeof (T).AssemblyQualifiedName];
return value;
}
public override void RemoveValue()
{
HttpContext.Current.Items.Remove(typeof (T).AssemblyQualifiedName);
}
public override void SetValue(object newValue)
{
HttpContext.Current.Items[typeof (T).AssemblyQualifiedName]
= newValue;
}
}
First request to page one: Shows values.
First web request to page two:Updates values.
Second web request to page one: Shows old values.
Second web request to page two: Shows new values.
I have to restart the VS development server to get page one to show the new values.
So how can a context a) live between page requests and b) be specific to a page?
This had nothing to do with EF. The generated UI was out of sync with the entity and the entity was throwing validation errors which weren't being reported in the UI. It would have helped if the scaffolding templates had generated a validation summary which didn't only show model level errors.
Related
Gives a 500 response code when the cancel button is pressed multiple types by the users.
Not causing performance issues but just a lot of clutter in application insights.
Any way to filter this out would be helpful.
Nothing is shown in the telemetry to share too, only the API method that is been called with a 500 code and time. sharing the screenshot of that.
Since you know the response code is 500, you can use telemetry processor to filter out these kinds of request with code 500.
Assume you're using .NET core, you can follow the steps below:
Create a class which implements ITelemetryProcessor, then filter out the request whose response code is 500(or more conditions as per your need.). The sample code looks like below:
public class IgnoreCancelFilter : ITelemetryProcessor
{
private ITelemetryProcessor Next { get; set; }
// next will point to the next TelemetryProcessor in the chain.
public IgnoreCancelFilter(ITelemetryProcessor next)
{
this.Next = next;
}
public void Process(ITelemetry item)
{
var request = item as RequestTelemetry;
if (request != null &&
request.ResponseCode.Equals("500", StringComparison.OrdinalIgnoreCase))
{
// To filter out an item, return without calling the next processor.
return;
}
// Send everything else
this.Next.Process(item);
}
}
Then, register it in ConfigureServices method of your Startup.cs class.
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddApplicationInsightsTelemetry();
services.AddApplicationInsightsTelemetryProcessor<IgnoreCancelFilter>();
}
If the programming language is not .NET core, you can find the proper method for .NET framework / js etc. in this article.
I can see in the source code of Prism this
Container.RegisterType<INavigationService, UnityPageNavigationService>(_navigationServiceName);
Why is it using a specific name? Why not have this:
Container.RegisterType<INavigationService, UnityPageNavigationService>();
I am asking because I'm having a hard time with child view-models:
class ItemViewModel : BindableBase
{
public ItemViewModel(INavigationService navigationService)
{
}
}
and I'm creating items on a page:
class MainPageViewModel : BindableBase
{
public IEnumerable<ItemViewModel> Items { get; private set; }
public MainPageViewModel(Funct<ItemViewModel> itemFactory)
{
}
public void OnNavigatedTo(NavigationParameters parameters) {
Items = ... // Create items, where each item is created using itemFactory
}
}
But the DI fails, it throws exception because it cannot create ItemViewModel:
Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the
dependency failed, type = "MyApp.ViewModels.ItemViewModel", name =
"(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, Prism.Navigation.INavigationService, is an interface and cannot be
constructed.
Are you missing a type mapping?
In Xamarin Forms navigation is based on the page being Navigated from. As such the Prism Forms PageNavigationService must be aware of the page which is associated with that particular instance of the service. In order to facilitate this, we register the service with a "secret" key, and then resolve the service and pass it in using the named instance "navigationService" for the ViewModel to consume.
You should not be using the NavigationService outside of the context of a ViewModel unless of course you are performing an absolute navigation (resetting Application.MainPage).
Note that each DI Container handles this a little differently, and each one uses a slight variation of the registration key, all of which is easy enough to look up with Prism being Open Source.
I come from "regular" asp.net so i'm a bit (totally) lost with MVC.
What I was doing with my own asp.net programmation pattern :
I have one custom class objet which represent the "page" and its properties (like mypage.loadJquery, mypage.isLogged, mypage.Title, custom cache logic, etc.)
This class is instanciate once on top of each ASHX page, I then manipulate a stringbuilder to produce HTML and spit it right at the browser at the end.
Having only one request on the ASHX page, i can use my page object instanciated at the top till the end when calling final response.write
Now i'm trying to go for MVC. I "kind of" understood the M/V/C model and the routing concept. I would like to keep my custom "page" object but I lost my page life cycle and I definitely don't know how to instanciate my page object ONCE in at the top of every call.
I need this instanciated ONCE shared object across every models, controllers, views, partial views, htmlhelper...
I realize MVC pattern might be confusing for me at this moment, bu how could I try to reproduce my need ?
(Very concrete exemple : On every request i need to check if the user is logged via his cookies. If it is I round trip the database to get user infos. Then I DO NEED THESE INFOS ON PRATICALLY EVERY model / controller / view of the app, but of course don't want to round back each time to security check and database querying, how can i have these info on the whole mvc cyle ?)
In my project I create interface IViewModel that contains all fields that I need in my layout/masterpage and set is as model of it so I can easily use them:
IViewModel.cs
public interface IViewModel
{
string Title { get; set; }
User User { get; set; }
}
Layout.cshtml
#model IViewModel
<html>
<head>
<title>#Model.Title</title>
</head>
<body>
#if (Model.User.IsAuthenticated) {
You are logged as #Model.User.Name
}
</body>
</html>
All my models implement that interface (or inherit from ViewModelBase that is default implementation of that class). Additionally I have custom action filter that check if returned ActionResult is (Partial)ViewResult and if Model of it implement my IViewModel interface and fill data in that interface.
public FillViewModelAttribute : ActionFilterAttribute
{
public override OnActionExecuted(ActionExecutedContext context)
{
var viewResult = context.Result as ViewResult;
if (viewResult != null && viewResult.Model is IViewModel)
{
var viewModel = (IViewModel)viewResult.Model;
// fill data
}
}
}
I created many projects like this. Basically, you can create a base controller class where all the other controllers inherit from it.
[Authorize]
public class BaseController : Controller
{
private Instructor _G_USER = null;
protected Instructor G_USER
{
get
{
if (_G_USER == null)
{
_G_USER = Your DB query here
ViewData["G_USER"] = _G_USER;
}
return _G_USER;
}
}
}
Then in your every child class, you can do
[Authorize]
public class YourController : BaseController
{
public ActionResult Index()
{
if(!G_USER.CAN_DO_THIS) throw new NoPermissionException();
return View();
}
}
To use the User in the view, create an extension method.
public static class ExtentionMethods
{
public static USER G_USER(this ViewPage page)
{
return (USER)page.ViewData["G_USER"];
}
}
Then use in the page like this
<%=this.G_USER().....%>
I recently read Phil Haack's post where he gives an example of implementing Model View Presenter for ASP.NET. One of the code snippets shows how the code for the view class.
public partial class _Default : System.Web.UI.Page, IPostEditView
{
PostEditController controller;
public _Default()
{
this.controller = new PostEditController(this, new BlogDataService());
}
}
However, here the view constructs the instance of the BlogDataService and passes it along to the presenter. Ideally the view should not know about BlogDataService or any of the presenter's lower layer dependencies. But i also prefer to keep the BlogDataService as a constructor injected dependency of the presenter as it makes the dependencies of the presenter explicit.
This same question has been asked on stackoverflow here.
One of the answers suggests using a service locator to get the instance of the BlogDataService and passing it along to the presenter's constructor.This solution however does not solve the problem of the view knowing about the BlogDataService and needing to explicitly get a reference to it.
Is there a way to automatically construct the presenter object using an IoC or DI container tool such that the view does not have to deal with explicitly creating the BlogDataService object and also injecting the view and service instances into the presenter's constructor. I prefer to use the constructor injection pattern as far as possible.
Or is there a better design available to solve the problem?. Can there be a better way to implement this If i am building a WinForms application instead of a ASP.NET WebForms application?
Thanks for any feedback.
Yes there is. For example using StructureMap in a webform constructor:
public partial class AttributeDetails : EntityDetailView<AttributeDetailPresenter>, IAttributeDetailView
{
public AttributeDetails()
{
_presenter = ObjectFactory.With<IAttributeDetailView>(this).GetInstance<AttributeDetailPresenter>();
}
....
}
and as you can see here presenter needs view and service injected
public AttributeDetailPresenter(IAttributeDetailView view, IAttributeService attributeService)
{
MyForm = view;
AppService = attributeService;
}
You can also use StructureMap BuildUp feature for webforms so that you can avoid using ObjectFactory directly in your view.
I did exactly this. The solution is based on Autofac, but can be implemented on top of any container.
First, define an interface representing the authority for presenting views in a request to the MVP system:
public interface IMvpRequest
{
void Present(object view);
}
Next, create a base page which has a property of that type:
public abstract class PageView : Page
{
public IMvpRequest MvpRequest { get; set; }
}
At this point, set up dependency injection for pages. Most containers have ASP.NET integration, usually in the form of HTTP modules. Because we don't create the page instance, we can't use constructor injection, and have to use property injection here only.
After that is set up, create event arguments representing a view which is ready to be presented:
public class PresentableEventArgs : EventArgs
{}
Now, catch the events in PageView and pass them to the request (present the page as well):
protected override bool OnBubbleEvent(object source, EventArgs args)
{
var cancel = false;
if(args is PresentableEventArgs)
{
cancel = true;
Present(source);
}
else
{
cancel = base.OnBubbleEvent(source, args);
}
return cancel;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Present(this);
}
private void Present(object view)
{
if(MvpRequest != null && view != null)
{
MvpRequest.Present(view);
}
}
Finally, create base classes for each type of control you'd like to serve as a view (master pages, composite controls, etc.):
public abstract class UserControlView : UserControl
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EnsureChildControls();
RaiseBubbleEvent(this, new PresentableEventArgs());
}
}
This connects the control tree to the MVP system via IMvpRequest, which you'll now have to implement and register in the application-level container. The ASP.NET integration should take care of injecting the implementation into the page. This decouples the page entirely from presenter creation, relying on IMvpRequest to do the mapping.
The implementation of IMvpRequest will be container-specific. Presenters will be registered in the container like other types, meaning their constructors will automatically be resolved.
You will have some sort of map from view types to presenter types:
public interface IPresenterMap
{
Type GetPresenterType(Type viewType);
}
These are the types you will resolve from the container.
(The one gotcha here is that the view already exists, meaning the container doesn't create the instance or ever know about it. You will have to pass it in as a resolution parameter, another concept supported by most containers.)
A decent default mapping might look like this:
[Presenter(typeof(LogOnPresenter))]
public class LogOnPage : PageView, ILogOnView
{
// ...
}
I have a very strange problem: NHibernate crashes when being called from a web user control.
I am working on a ASP.Net (2.0) web page which uses NHibernate to access a database.
And I have a simple factory class to access a column CurrentStepNumber in the table ProjectInfo:
public class ProjectEntity
{
private int? _currentStepNumber;
public virtual int? CurrentStepNumber
{
get { return _currentStepNumber; }
set { _currentStepNumber = value; }
}
public static ProjectWizardEntity GetById(int id, bool shouldLock)
{
return RepositoryFactory.ProjectWizardRepository.GetById(id, shouldLock);
}
public static ProjectWizardEntity GetById(int id)
{
return GetById(id, false);
}
public virtual void Save()
{
RepositoryFactory.ProjectWizardRepository.Save(this);
}
public virtual void SaveOrUpdate()
{
RepositoryFactory.ProjectWizardRepository.SaveOrUpdate(this);
}
}
This class is accessed via a proxy class, so that everytime a new value is assigned it is flushed to the database:
public class DBHelper
{
ProjectEntity _projectEntity;
ProjectEntity GetProjectEntity()
{
if (_projectEntity == null)
_projectEntity = //get or create a new one;
return _projectEntity ;
}
public int? CurrentStepNumber
{
get
{
return (CurrentProjectId > 0) ? CurrentProjectWizardEntity.CurrentStepNumber : 0;
}
set
{
if (CurrentProjectId > 0)
{
CurrentProjectWizardEntity.CurrentStepNumber = value;
CurrentProjectWizardEntity.SaveOrUpdate();
}
}
}
}
Now the problem:
When I access CurrentStepNumber from the test.aspx page, everything works perfectly
When I read this field from the web user control (test.ascx) which is used on test.aspx page it is still OK
However when I try to assign a value to CurrentStepNumber in the code behind the control (test.ascx) I always get an exception:
NHibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
Actually SaveOrUpdate method of the NHibernate Repository throws the exception.
I could not figure out what could be the problem here, so any help will be appreciated.
I think that You have a session management problem here. How is RepositoryFactory.ProjectWizardRepository.GetById creating and possibly disposing the NHibernate session? Does it create and then close a session?
It seems that DBHelper.GetProjectEntity() is creating or loading a ProjectEntity. Later, when CurrentStepNumber's setter i called, You insert or update the object to the database.
The problem is that when DBHelper.GetProjectEntity() is loading an existing object and later closing the session after it has been loaded but keep the object around, we are entering deep water. When the object is later updated, You set a new value for CurrentStepNumber and send the object to NHibernate to save. The problem here is that the object is not associated with the new session that is created and closed during saving. Nhibernate then gets confused since a new object is discovered that is not loaded from current session but it has an id of an existing object.
For a solution, Google for "NHibernate asp.net session management" and You will get a number of good hits about how to use the ASP.NET request cycle as a unit of work.