ASP.NET Core View - c#

I am not sure how to get my SQL view to actually be read from the .cshtml file. I have my model created to relate to the view and have added the DbSet to the appdbcontext class. I have also done the keyless on the onModelBuilder and created this
public async Task<IActionResult> PreviewEmailAsync()
{
var myTableResults = _context.WetWeatherReportViews.FromSqlRaw(
"Select * from dbo.WetWeatherReportView").ToList();
ViewBag.Data = myTableResults;
return View();
}
Not sure how to get the view to showcase the information within, I have tried multiple different methods and believe the ViewBag is my closest one, but don't believe I am doing it right. I am unable to get it to work and not sure what I am missing. Thank you for the help!

Related

Entity Framework tracks change after second update

The application was built on a bunch of asp .net core mvc and entity framework.
I have a map with markers on it. I want to change the parameters of a certain object through textboxes. The request from the frontend is written in axios, and it works flawlessly. From the first time I get the changes in the database. (mysql, provider: pomelo.mysql).
When I try to access the get request for the first time, I get the old state of the object.
HttpGet request is described here:
public async Task<IEnumerable<Poi>> GetPois()
{
var pois = await _poiService.GetPois();
if (pois.Status == Domain.Enum.StatusCode.Ok)
{
return pois.Data;
}
else { return null; }
}
I have an interface that describes the necessary set of manipulations with the Poi object.
IPoiService is described here:
public interface IPoiService
{
Task<BaseResponse<IEnumerable<Poi>>> GetPois();
Task<BaseResponse<Poi>> GetPoi();
Task<BaseResponse<bool>> DeletePoi();
Task<BaseResponse<Poi>> CreatePoi();
Task<BaseResponse<Poi>> UpdatePoi(Poi entity);
}
The service for working with the Poi object is described here:
public async Task<BaseResponse<IEnumerable<Poi>>> GetPois()
{
try
{
return new BaseResponse<IEnumerable<Poi>>
{
Data = await _poiRepository.GetAll().ToListAsync(),
Status = Domain.Enum.StatusCode.Ok
};
}
catch(Exception ex)
{
return new BaseResponse<IEnumerable<Poi>>
{
Status = Domain.Enum.StatusCode.InternalServerError,
Description = $"[GetPois]: {ex.Message}"
};
}
}
BaseResponse and the corresponding interface represents the response from the database, so it doesn't affect the update problem in any way.
I also have a repository that directly implements instance operations at the database level.
The repository is described here:
public class PoiRepository : IBaseRepository<Poi>
{
private readonly ApplicationDbContext db;
public PoiRepository(ApplicationDbContext db)
{
this.db = db;
db.Database.OpenConnection();
}
public Task Create(Poi entity)
{
throw new NotImplementedException();
}
public Task Delete(Poi entity)
{
throw new NotImplementedException();
}
public IQueryable<Poi> GetAll()
{
return db.Pois;
}
public Poi Update(Poi entity)
{
db.Pois.Update(entity);
db.SaveChanges();
return entity;
}
}
Thus, I get the problem that in order to get the current data, I need to perform two HttpGet requests, and only after that EF Core will return its current value to me.
The reason that Update(entity) sends off warning bells is that you are passing entities between server and client and back. When a controller returns a View(entity) you are sending a reference entity to the view engine to build the view. The view's #Model allows you to apply bindings but it is not a client-side copy of the entity. However, when your form submit or Ajax call etc. calls back with the #model that is NOT an entity, let alone the entity the view engine was given. It will only be a copy of data and only as complete as the view bindings could populate.
So it's hard to deduce what exactly you are witnessing without stepping through the application, but my gut says you are most likely getting confused by what you think is passing entity references around. Think of it this way, in your POST actions you could accept a set of ints, strings, and such for each of the values of the model, or a completely different class definition (DTO/ViewModel) with the same fields as the entity. ASP.Net would attempt to fill in using the data submitted with a Form POST or Ajax call. By accepting an "Entity" you are just telling EF to populate the data into a new untracked entity class. It's not the same instance as a DbContext originally loaded, and the DbContext is a different instance (or should be) than when the entity was originally loaded, it isn't tracking the entity that was originally loaded.
The resulting object will only contain the details that the view happened to have stored in the individual bound controls, pieced back together behind the scenes.
My recommendation is simply to never pass entities to, and especially from a view. Use an explicit ViewModel to represent the state sent to and from a view, then in your Update method:
Fetch the actual entity using the ViewModel ID,
Check a concurrency token (RowVersionNumber / Timestamp) to ensure no changes were made to the DB since you originally fetched the data to populate the View. (optional, but recommended)
Validate the data in your view model
Copy the data from the view model into the Entity. (Automapper can help here)
SaveChanges()
No use of Update or Attach in the DbContext/DbSet.

How can I prevent form resubmission in MVC

My current situation is as follows.
I have a form that when it gets submitted, passes the model into the controller and it does what it needs to do. At the end it redirects to a confirmation page that also gets passed the same model. All of that works fine, except when I am on the confirmation page, whenever I reload the page it resubmits the form.
I've tried using TempData but when I use that it requires for my model to be serializable and my model uses other models inside it that were made by other people that all need to be serializable which would result in like 15-20 different classes all needing to become serializable which just doesnt seem reasonable.
Here is some of what I am working with:
[HttpPost]
public async Task<ActionResult> SubmitClaim(WarrantyClaim model)
{
... code ...
return BeddingWarrantyConfirmation(model);
}
public ActionResult BeddingWarrantyConfirmation(WarrantyClaim model)
{
return View("BeddingWarrantyConfirmation",model);
}
You could make use of the Post Redirect Get Pattern. You could return the following in SubmitClaim:
return RedirectToAction("BeddingWarrantyConfirmation", "CONTROLLER", model);
For more information, please see https://en.wikipedia.org/wiki/Post/Redirect/Get
This is a common problem in MVC development, you can follow the Post/Redirect/Get strategy to avoid the request.
https://en.wikipedia.org/wiki/Post/Redirect/Get

Keeping controller in scope

Yesterday i was working on my asp.net mvc application where i was trying to cache some data in a field while a certain controller was in scope. The field kept clearing every time a new view got opened.
Question:
Is it possible to keep your Controller in scope while you're browsing Views that are handled by said Controller?
private static List<string> _listOfStrings;
[Authorize]
public ActionResult ToView1()
{
_listOfStrings = new List<String>(){"test","test2"};
var model = new Model();
return View(model);
}
[Authorize]
public ActionResult FromView1ToView2()
{
var model = new Model(_listOfStrings);
//the issue at hand is that '_listOfStrings' is not persisted.
return View(model);
}
Anyone got an idea if this is possible? (The list is big, so i would prefer not sending it through the model into the view and vice versa)
You need to read about an ASP.NET MVC lifecycle.
Short answer: no, you can't cause Controller is destroyed after a call of an action. Detail answer: you can store (cache) data in a TempData or in a Session properties.
_listOfStrings is a different variable to listOfStrings. You are not writing to or reading from the static field. In the code you have presented, _listOfStrings is not even defined.
Use one static variable and this code will work.

Implement ActionResult that just writes the razor _Layout + a const string body

I'm writing a ReactJs application with jspm and a lot of my views end up looking like this
<script>System.import('customers')</script>
or
<script>System.import('invoicing')</script>
so what gets sent to the browser is the _Layout.cshtml (as defined by _ViewStart.cshtml`) and that simple body.
Since there's literally no variance here, I'd like to not have to create the view file at all (there's additional reasons for this as well). I'd like to be able to do
return new LoadJsModuleResult('customers');
or
return new LoadJsModuleResult('invoicing');
How would I go about writing LoadJsModuleResult?
I'm looking at the source for ViewResult and ViewEngineResult but it seems that at that point everything is already assembled with the assembly happening somewhere in ViewEngineCollection. I can track it as far as BuildManagerWrapper.GetCompiledType but then we get into the depths of System.Web.
Does anyone have any hints?
I'll note that convenience is not the only reason I want to do this, I'm also making a module system that this would work particularly well with.
you could have a view LoadJSModule.cshtml in shared containing
#model string
<script>System.import('#Model')</script>
and then in your controller return View("LoadJSModule", "modulename")
You could have a method in a Controller subclass all your controllers inherit from
public ViewResult LoadJSModule(string modulename) {
return View("LoadJSModule", modulename);
}
so you could return LoadJSModule("mymodule")

Insert-update-delete web GUI

I find myself creating Add/Edit/Delete/List GUI's so often that I'm sick and tired of it.
There must be some free package that solves this, right?
What I would like is something like this:
{
MyApplicationUser user = MyApplication.GetUserByID(1234);
EditForm form = new EditForm("Title: Edit User"); //this is the magic object
form.addFieldsFromObject(user);
}
function onFormSubmit(eventArgs e){
MyApplicationUser user = form.GetSubmittedData();
MyApplication.SaveUser(user);
}
AddFieldsFromObject would automatically create a html form with fields mathing the datatype of the public properties of the object I feed it with.
There are a number of frameworks that try to solve this problem. ASP.NET Dynamic Data may be a good place to start. It uses a template-based system to provide basic CRUD (Create, Retrieve, Update, Delete) user interfaces with very minimal custom code.
ASP.NET MVC also does a pretty good job with its editor models:
// View code
#using(Html.BeginForm(...)) {
#Html.EditorForModel()
}
// Action code
public ActionResult ShowForm(int userId)
{
var model = // get model from user ID;
return View(model);
}
public ActionResult SaveForm(Model model)
{
if(ModelState.IsValid)
{
// Save model
}
}
LightSwitch tries to solve this same problem by auto-generating basic scaffolding code for you to produce an experience similar to Microsoft Access. But since it's using actual C# code, you can alter the code to provide more functionality if you find that your needs have grown beyond the original scope of the project.

Categories

Resources