ASP.NET MVC 3 Site Loading Is Extremely Slow - performance

I really don't know where to begin with this question, but the site I'm working on at times has some really slow page loads. Especially after doing a build, but not always. I usually have to refresh the page 5-10 times before it actually comes up. I guess I am trying to see where exactly I should begin to look.
ASP.NET MVC 3
Ninject
AutoMapper
Entity Framework Code First 4.1
SQL Server 2008
Razor
UPDATES
Concerning some of the questions, it can do this long loading on every page, but after it loads its fairly quick on all the pages.
After posting this and getting your replies I started the application and it is still loading and probably won't ever load unless I click reload on the browser.
No caching, and the EF models aren't huge.
I am using Razor and Visual Studio 2010 with 6 GB of memory and an I7 processor.
I am using IIS Express and the default web server when debugging. It also does this on IIS7 on the main server.
I may look into the MVC Profiler and Glimpse to see what I can find.
Below I have some code this runs when it hits the homepage. I would say it never loads when I first start up the server. I put a break point at var model which never gets hit. If I reload the page then it does.
public ActionResult Index()
{
var model = new HomeViewModel();
model.RecentHeadlines = _headlineService.GetHeadlines(1, Config.RecentHeadlinesPageSize, string.Empty);
return View(model);
}
Below is my datacontext setup also.
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private DataContext _dataContext;
public DataContext Get()
{
return _dataContext ?? (_dataContext = new DataContext());
}
protected override void DisposeCore()
{
if (_dataContext != null)
_dataContext.Dispose();
}
}
public class Disposable : IDisposable
{
private bool isDisposed;
~Disposable()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!isDisposed && disposing)
{
DisposeCore();
}
isDisposed = true;
}
protected virtual void DisposeCore()
{
}
}
public class UnitOfWork : IUnitOfWork
{
private readonly IDatabaseFactory _databaseFactory;
private DataContext _dataContext;
public UnitOfWork(IDatabaseFactory databaseFactory)
{
_databaseFactory = databaseFactory;
}
protected DataContext DataContext
{
get { return _dataContext ?? (_dataContext = _databaseFactory.Get()); }
}
public void Commit()
{
DataContext.Commit();
}
}

I'd start by checking what the timeouts are set to in IIS for the process to be recycling itself.
I'm also a very big fan of the MVC Mini-Profiler which could show you exactly how long various parts of your page load are taking, definitely take a look at it.
Edit:
It is worth noting that the Glimpse project is also great for this task these days.

Sounds like it might be an issue with IIS AppPool recycling if you're experiencing it after builds or after periods of inactivity.
To help with AppPool timeouts you can utilize a batch file I created to help mitigate the issue.
That won't solve the problem for you after new builds because your ASP.NET MVC application needs to be JIT-compiled upon first run. If you're really eager to eliminate that issue, you can use ASP.NET precompliation.

Try Glimpse or use ASP.NET Tracing.
You could also precompile your views if you are using the Razor view engine via Razor Single File Generator for MVC.

It depends on what happened in your previous run, sometimes if you throw an error and don't clear that out then you will have issues running the application. It helps to restart the browser every time you build if there was an error.
However, this could be an issue of caching. It is possible that your database is caching due to poorly maintained context disposing. This would cause the lookups to run faster and faster as they were encountered in pages. Make sure you always call .dispose() when done with your database transactions.

funny - I've noticed something similar once with unity and mvc but the problem I believe resolved itself. You could also try ants profiler to see if the problem is outside of MVC.
If you let a single request sit there (without requesting 5+ times) what happens?
Let a single request run - is ANY of your code hit? (setup logging log4net, nlog, etc) to run application_start, etc to see if any code is getting called after the compile.

Related

Error trying to scaffold a view in ASP.NET Core 6.0 MVC

I'm trying to scaffold a new razor view using Visual Studio. I select a template, my model and my DbContext, then I get the error message shown below.
Things to note. My models, my DbContext and my website are all in different projects. From the message below I am using AddDbContext and I have a constructor that accepts a DbContextOptions<TContext> parameter.
I read a comment on a blog post that the issue is because my context is in another project. The comment referenced something about the need to inject the Configuration into the DbContext to get the connection string and manually add it in the OnConfiguring override.
I can't find any examples if this is correct or how to set it up. Any help would be appreciated.
EDIT:
Testing out the theory from the blog comment I mentioned above, I added this section into my DbContext. ConnectionString is a hardcoded string constant with my connection information. This does work and allow me to scaffold, so the question still remains. How can I inject this connection string into my DbContext to allow the scaffolding to work?
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(ConnectionString);
}
else
{
base.OnConfiguring(optionsBuilder);
}
}
EDIT: So after making this change, I checked in the code and had another developer pick it up. It appears this section above just needs to be there to allow scaffolding to work. He never changed the connection string to point to his environment. He no longer got the error above it just worked.
I am not sure about what is the actual problem but it seems like we were having problems creating DbContext at design time. I manually added the code below and it's working now. It's just a temporary solution tho.
public AppDbContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
optionsBuilder.UseSqlServer("Data Source=.;Initial Catalog=JwtTemplate;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
return new AppDbContext(optionsBuilder.Options);
}
Reference: https://stackoverflow.com/a/70559350

App Insights memory leak in background tasks

I am using Simple Injector DI in .NET web api (.net 4.8 framework) and have a wrapper class(my own implementation) around the telemetry client.
public class MyAppInsights : IMyAppInsights
{
private static TelemetryClient telemetry;
public MyAppInsights ()
{
if (telemetry == null)
{
telemetry = new TelemetryClient();
}
}
//other interface method implementations
}
simple injector startup configuration looks like
container.Register<IMyAppInsights , MyAppInsights >(Lifestyle.Singleton);
I am noticing lots of Httpwebrequest objects (app insights) are being added to memory and not released for a long running background tasks. This problem appeared only recently after implementing long running background tasks which was causing out of memory exceptions.
Any pointers on how to reduce/plug the memory leak / consumption would be greatly appreciated
You can try to remove Lifestyle.Singleton to see if you still have memory leak.
Also check the site for example.
https://docs.simpleinjector.org/en/latest/quickstart.html

NET Core Server Side multiple session Blazor

I'm trying to host my Blazor application on my server.
I spent all the summer on it and I just realized every time I open my website on new device it doesn't create a new session restarting from zero, but continues where I left it. The worst part is there is a login system behind it, so I feel super dumb at the moment.
I really need a big hint on how to fix this "not little" issue.
Is there a way to make server create new session every time someone open the website (without making it loose to other users)?
The solution should be use a Client Template instead, but the performance are really to slow.
UPDATE:
Accounts "user password" are:
- user user
- test test
Download project sample (requires Net Core 3.0)
[SOLUTION] itminus found the solution to my issue.
You have also to add in ConfigureServices in Startup.cs this services.AddScoped<Storage>();
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddScoped<Storage>();
}
every time I open my website on new device it doesn't create a new session restarting from zero, but continues where I left it.
I checkout your code and find that you're using Singleton Pattern to initialize the Storage. If I understand it correctly, this Storage singleton instance will be shared across different users (also across different devices). As this instance will be used to render the Main.razor page, there will be concurrency problems that you're experiencing now .
To fix that issue, the Storage instance should be limited within some specific connection. As you're using Blazor Server Side, you could register the Storage as a Scoped Service:
In Blazor Server apps, a scoped service registration is scoped to the connection. For this reason, using scoped services is preferred for services that should be scoped to the current user, even if the current intent is to run client-side in the browser.
Firstly, remove the static singleton instance :
public class Storage
{
private static Storage instance;
private Storage()
{
}
public static Storage GetInstance()
{
if (Storage.instance == null)
Storage.instance = new Storage();
return Storage.instance;
}
public List<Items>list {get;set;} = new List<Items>();
public string password {get;set;}
}
Register this Class as a scoped service:
services.AddScoped<Storage>();
And then inject this service in your Login.razor and Main.razor :
#inject project.Storage Storage
Finally, you need change all the Storage.GetInstance(). to Storage.:
Storage.list = Order;
...
Storage.password = password;
I notice that you're also creating the Importer/Additional instance using the Singleton Pattern. I would suggest you should refactor them to use Service Injection in a similar way.

Deploying MVC 3 with Code First EF , also using Web Deploy

I'm trying to deploy my first MVC website (using arvixe as my host) and I'm having problems with the database. When I develop on my local and I change anything on my Models (mapped on my DbContext) it wipes out my database and creates a new one (if it exists) or just completely create a database for my entities.
With that said, my problem is when I deploy it, my project that has all the controllers gets deployed and I can access my landing page but once I try to login (which triggers the creating of a database on my local) it will just give me an error and wouldn't try to create the database.
Not really sure what I'm missing on the steps, should I be creating the database at least without the records first?
This sounds like a permissions problem. The account you are running on your server most likely does not have permissions to DROP/CREATE tables.
When deploying to production / hosted server I generally do not rely on EF to create my schema. I copy my CREATE tabel scripts from my DEV enviorment to PRODUCTION and make sure my DBCONTEXT intialisation code is set NOT TO make any changes.
Try This:
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Data.Entity.ModelConfiguration.Conventions;
public class YourDbContext: DbContext
{
public YourDbContext()
: base("name = YourConnection")
{
Database.SetInitializer<YourDbContext>(new MigrateDatabaseToLatestVersion<YourDbContext, YourMigrationsConfiguration>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Your Building Rules
}
#region DbSets
public DbSet<YourTable> YourTables { get; set; }
#endregion
}
public class YourMigrationsConfiguration : DbMigrationsConfiguration<YourDbContext>
{
public YourMigrationsConfiguration()
: base()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
protected override void Seed(YourDbContext context)
{
/*sql script*/
}
}
So apparently the only way I can do the same thing that my App does in my local to my host is to have sysadmin permissions/account to drop the dbase. which is not happening...ever.. So I decided to just generate a script and run it remotely. I'm not sure how it will affect my database once i start doing alterations on tables and maintenance on the data. wish me luck.
oh btw, here's my source for the script
https://stackoverflow.com/a/10760985/639713

Problem with MVC3 AllowHtml attribute

I have a web app based on MVC3 (no beta or release candidate, RTM/RTW version) that has an action that accepts XML files for processing.
Of course, this seems evil to MVC because of possible attacks, so it doesn't allow it. Well, I try to put either AllowHtml on the model object as such:
public class XMLModel
{
[AllowHtml]
public string msg { get; set; }
}
Or I set ValidateInput to false on my action method such as this:
[ValidateInput(false)]
public ActionResult AddCDR(XMLModel model)
{
}
The reason for having a "strongly" typed model in the first place was that I originally tried to have a string value named "msg" as the action method parameter, but that always came back empty.
Now, when someone posts to this form, either on the same machine or from a networked computer, the msg field is always blank.
I have verified with WireShark that the data is actually in the request.
Now, one interesting thing. This should not be necessary with MVC 3. Yet it makes a slight difference.
If I add this to my web config:
<httpRuntime requestValidationMode="2.0" />
It works for requests originating from the local computer, but it does NOT work from another system.
I think the AllowHtml version seems elegant - if only it worked.
I have also found out about a bug in RC2 - again, this should not affect me, but I tried to add the following in Application_Start() anyway:
ModelMetadataProviders.Current = new DataAnnotationsModelMetadataProvider();
As expected, it makes no real difference.
Everything works as expected on my development computer (Win7x64, VS2010), but on the target system (Win2008R2x64, IIS7.5) the above problems are giving me a hard time.
Very important point to note: If I post to the action with no angle brackets, I get the form data as expected. As soon as the angle brackets show up, though, either my action isn't called at all, or it doesn't find the form data, neither in action method parameters or in for instance Request.Params["msg"] where it should be.
Any ideas to allow the XML through?
UPDATE
I've tried to work my way around this while waiting for anyone to come up with an answer here. I have not been able to solve it yet, but I have checked a few additional details;
First, I verified that the ASP.NET MVC 3 version installed on both my development computer and on the web server is the same; v3.0.20105.0 (according to Add/Remove programs).
The web application was actually created with the MVC3 beta, then converted to RC1 and RC2 as they came out, and finally to the RTM version. This meant I had to modify some code because of the ViewBag change. However, since I didn't know exactly what else had changed, I created a brand new MVC3 application with the RTM version, created a controller by the same name, with the same action method, taking a model object similar to the currently used one, renamed the old web app directory and put this new one in place. Exactly the same thing happens - i.e. the parameter with the AllowHtml attribute comes through with all content when the request is made from the local machine, but if it comes from a remote machine, then the HTML (XML actually) is stripped out.
There is no exception. I've installed Elmah and verified this - no exception occurs, my action method is apparently just called with anything looking like XML stripped out from the parameters to the method.
Needless to say, this is driving me crazy. I had some advice yesterday to look at the source code of MVC3, but unfortunately that doesn't really help me, as I can't see anything obviously wrong there, and I can't debug code on the server in question.
Any insights still highly desired, thanks! :)
I cannot reproduce this.
Model:
using System.Web.Mvc;
namespace MvcApplication3.Models {
public class XmlModel {
[AllowHtml]
public string msg { get; set; }
}
}
Controller:
using System.Web.Mvc;
using MvcApplication3.Models;
namespace MvcApplication3.Controllers {
public class HomeController : Controller {
public ActionResult Index() {
return View();
}
[HttpPost]
public ActionResult Index(XmlModel model) {
return View();
}
}
}
View:
#model MvcApplication3.Models.XmlModel
#using (Html.BeginForm()) {
<div class="editor-label">
#Html.LabelFor(model => model.msg)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.msg)
#Html.ValidationMessageFor(model => model.msg)
</div>
}
These were added to a default empty MVC 3 project. Everything posts fine. When I remove [AllowHtml], it generates the appropriate error message.
I am answering this myself because this was an obscure situation, and MVC3 was not the problem.
The system that POSTed data to my application was doing so with malformed data. In addition to that, I was told that they were also POSTing to an older MVC2 application that worked just fine - this was wrong, it turned out they were GETting in that case, and GET they happen to do correctly.
If anything, fairly thorough testing has confirmed that the AllowHtml attribute actually works very well. Never trust your input, tho. :)

Resources