Deploying MVC 3 with Code First EF , also using Web Deploy - asp.net-mvc-3

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

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

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.

ASP.NET MVC 3 Site Loading Is Extremely Slow

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.

How to reference an initialized embedded RavenDB instance in a Class Library?

My scenario is this:
I have a custom RavenDB membership provider that is implemented in a class library (DLL). This provider needs to access a database to store and retrieve User and Role information. I'd like to use the same app database to store membership information to avoid having one more database.
I don't know how to get a reference to the already initialized database (app database) inside the class library code. I think I'm going the wrong way here... :)
Some code:
bool embeddedStore = Convert.ToBoolean(config["enableEmbeddableDocumentStore"]);
if (embeddedStore)
{
_documentStore = new EmbeddableDocumentStore()
{
// Here I'm using the same connection string used by the app.
// This gives me an error when I try to open a session in the DocumentStore.
ConnectionStringName =
config["connectionStringName"]
};
}
else
{
_documentStore = new DocumentStore()
{
ConnectionStringName =
config["connectionStringName"]
};
}
This is the connection string present in Web.config:
<add name="RavenDB" connectionString="DataDir = ~\App_Data\Database" />
How can I reuse the same database within the custom membership provider? Any ideas?
I thought about moving the class library code files to the Web project. This way I could get a reference to the DocumentStore easily, but the code wouldn't be as organized as I'd like.
I also tried to use 2 RavenDB databases: 1 for the app and 1 for the membership provider, but as I'm running RavenDB in its embeddable fashion I couldn't get it working.
These are the errors I got during my attempts so far:
RavenDB Could not open transactional storage.
Temp path already used by another database instance.
You need to pass the instance of the opened document store to your dll.
You can do that using a container or by providing an API call to do that.
You can't have two instance using the same db.

How to speed up Azure deployment from Visual Studio 2010

I have Visual Studio 2010 solution with an Azure Service and an ASP.NET MVC 3 solution that serves as a Web Role for the Azure service. No other roles attached to the service other than that.
Every deployment to the Azure staging (or production, for that matter) environment takes up to 20 minutes to complete, form the moment I click publish on Visual Studio until all instances (2) are started.
As you can imagine this makes it a PITA to publish often, or to quick-fix some bugs. Is there a way to speed the process up? Would it be faster to upload the package to de Blob storage and upgrade from there? How would I go about achieving that?
I feel on-line docs on Azure leave a lot to be desired. Particularly when it comes to troubleshooting by the way.
Thanks.
One idea for reducing the need (and frequency) for redeploying is to move static content into blob storage, external to the package. For instance, move your css and javascript to blob storage, along with images. Once this is done, you'd only have to recompile / redeploy for .NET code changes. You can upload updated css, at any time, to blob storage. If you want to test this in staging first, you could always have a staging vs. production container name for your static content and store that container name in a config setting.
This doesn't change the deployment time when you do need to redeploy, but at least you can reduce how often you go through that process...
You should enable Web Deploy in your Azure project. It works this way :
1/ Create a RDP account (don't forget, you need to upload a certificate with its private key so that Azure can decipher the password). That is hidden in the Deploy Dialog Box for your Azure deployment project.
2/ Enable Web Deployment - same place
Once you've published the app that way, right-click in the web application (not the azure deployment project) and select Publish. The pop-up has everything defined except the password, enter that as well and you'll upload your changes to Azure in a matter of seconds.
CAVEAT : this is meant for single-instance web apps, definitely not the way to go for a production upgrade strategy, and the Blob storage answer already mentioned is the best option in that case.
Pierre
My solution to this problem is only to push a new package when I am changing code in the RoleEntryPoint or with the Service Definition. In Azure 1.3 you now have the ability to use Remote Desktop Connection. Using RDC, I will compile my code locally and use copy/paste to place it on the Azure server in the appropriate directory. Once the production code is running correctly, I can then push the fully tested version to staging and then do a VIP swap. This limits the number of times I actually have to deploy a package.
You actually have quite a long window in which you can keep modifying your code in Azure before you have to publish a new package. The new package is only really needed for those cases where Azure has to shutdown/restart your role instance.
It's a nice idea to try uploading your project to blob storage first, but unfortunately this is what Visual Studio is doing for you behind the scene anyway. As has been pointed out elsewhere, most of the time in doing the deploy is not the upload itself, but the stopping and starting of all of your update domains.
If you're just running this site in a development environment, then the only way I know to speed it up is to run just one instance. If this is the live environment, then... sorry, I think you're out of luck.
So that I don't have to deploy to the cloud to test minor changes, what I've found works quite well is to engineer the site so that it works when running in local IIS just like any other MVC site.
The biggest barrier to this working are settings that you have in the cloud config. The way we get around this is to make a copy of all of the settings in your cloud config and put them in your web.config in the appSettings. Then rather than using RoleEnvironment.GetConfigurationSettingValue() create a wrapper class that you call instead. This wrapper class checks RoleEnvironment.IsAvailable to see if it is running in the Azure fabric, if it is, it calls the usual config function above, if not, it calls WebConfigurationManager.AppSettings[].
There are a few other things that you'll want to do around getting the config setting change events which hopefully you can figure out from the code below:
public class SmartConfigurationManager
{
private static bool _addConfigChangeEvents;
private static string _configName;
private static Func<string, bool> _configSetter;
public static bool AddConfigChangeEvents
{
get { return _addConfigChangeEvents; }
set
{
_addConfigChangeEvents = value;
if (value)
{
RoleEnvironment.Changing += RoleEnvironmentChanging;
}
else
{
RoleEnvironment.Changing -= RoleEnvironmentChanging;
}
}
}
public static string Setting(string configName)
{
if (RoleEnvironment.IsAvailable)
{
return RoleEnvironment.GetConfigurationSettingValue(configName);
}
return WebConfigurationManager.AppSettings[configName];
}
public static Action<string, Func<string, bool>> GetConfigurationSettingPublisher()
{
if (RoleEnvironment.IsAvailable)
{
return AzureSettingsGet;
}
return WebAppSettingsGet;
}
public static void WebAppSettingsGet(string configName, Func<string, bool> configSetter)
{
configSetter(WebConfigurationManager.AppSettings[configName]);
}
public static void AzureSettingsGet(string configName, Func<string, bool> configSetter)
{
// We have to store these to be used in the RoleEnvironment Changed handler
_configName = configName;
_configSetter = configSetter;
// Provide the configSetter with the initial value
configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
if (AddConfigChangeEvents)
{
RoleEnvironment.Changed += RoleEnvironmentChanged;
}
}
private static void RoleEnvironmentChanged(object anotherSender, RoleEnvironmentChangedEventArgs arg)
{
if ((arg.Changes.OfType<RoleEnvironmentConfigurationSettingChange>().Any(change => change.ConfigurationSettingName == _configName)))
{
if ((_configSetter(RoleEnvironment.GetConfigurationSettingValue(_configName))))
{
RoleEnvironment.RequestRecycle();
}
}
}
private static void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
{
// If a configuration setting is changing
if ((e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange)))
{
// Set e.Cancel to true to restart this role instance
e.Cancel = true;
}
}
}
The uploading itself takes a bit more than a minute most of the time. It's the starting up of the instances that take up most of the time.
What you can do is to deploy your fixes to staging first (note that it costs money so don't let it be there for too long). Swapping from staging to production only takes a couple of seconds. So while your application's still running you can upload the patched version, let your testers test it on staging and when they give the go then simply swap it to production.
I haven't tested your possible alternative approach by first uploading to blob storage first. But I think that's overhead as it doesn't speed up starting up the instances.

Resources