A few months back, there was a job position who required a pre interview task assessment. I'm actually new to .NET, so I passed and decided to apply to another job which didn't require .net as much. Long story short. Since then, the idea of solving this problem hunts me and It bothers me that I was able to get really close to the solution and didn't actually finished it.
So, if anybody wants to practice their .net /webapi2/ angular skills here it is:
screenshot
I get a weird error (NULL values) when I'm almost finishing this task
My Homecontroller.cs
namespace KLab.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Title = "Home Page";
return View();
}
public JsonResult GetSections()
{
var db = new KLabDBEntities();
var samples = db.Samples.Include("User").Include("Status").ToList();
return Json(samples, JsonRequestBehavior.AllowGet);
}
}
}
Since this is WEb API I've changed the angular code to the following:
my App.js
var myApp = angular.module('myApp', []);
myApp.controller('maincontroller', function ($scope, SampleService) {
getSamples();
function getSamples() {
SampleService.getSamples()
.success(function (Samples) {
$scope.Samples = Samples;
});
}
});
my service.js
myApp.factory('SampleService', ['$http', function ($http) {
var urlBase = 'http://localhost:35656/api';
var SampleService = {};
SampleService.getSamples = function () {
return $http.get(urlBase + '/Samples');
};
return SampleService;
}]);
My index.cshtml
<h2>Samples</h2>
<div ng-controller="maincontroller">
<table class="table">
<tr>
<th>Samples Id </th>
<th>Code Number</th>
<th>Date </th>
<th>User Id </th>
<th>Status Id </th>
</tr>
<tr ng-repeat="Sample in Samples">
<td>{{Sample.SampleId}} </td>
<td>{{Sample.CodeNumber}} </td>
<td>{{Sample.Date.replace('/Date(','').replace(')/','') | date:"MM/dd/yyyy"}} </td>
<td>{{Sample.UserId}}</td>
<td>{{Sample.StatusId}}</td>
</tr>
</table>
</div>
Everything else is default from the WeBAPI2 template from Visual Studio.
so my Models are generated by Entity Framework:
When I build i get:
Samples Id CodeNumber Date UserId StatusId
data data data 1 6
data data data 2 4
My goal is to change those id numbers to the actual data of the tables , they are foreign key values
I get no values in that column and when I call the JSON I get:
[{"SampleId":1,"CodeNumber":129076,"Date":"2015-01-02T00:00:00","UserId":6,"StatusId":3,"Status":null,"User":null},
{"SampleId":2,"CodeNumber":850314,"Date":"2015-06-15T00:00:00","UserId":7,"StatusId":3,"Status":null,"User":null},
{"SampleId":3,"CodeNumber":176033,"Date":"2015-07-31T00:00:00","UserId":7,"StatusId":0,"Status":null,"User":null},
{"SampleId":4,"CodeNumber":129629,"Date":"2015-01-21T00:00:00","UserId":3,"StatusId":0,"Status":null,"User":null},"
which is odd since , Status and user are null
Somebody has suggested that this "joins" must be done within a view on the Database itself and then should be called with angular. like a SQL view or using LINQ. Unfortunately, I do not know LINQ but I do know SQL I guess I can create a view with all the tables. Therefore the question is. How can i replace those ID values to the actual data that are related to those foreign keys (userid, statusid) ?
Here's the bulk data's screenshot:
bulk data
Related
What I am trying to achieve is 2 things:
send a value I get from an external source (An API) inside my controller for processing. "to check if that ID exists in my database. if not add it" but my issue is that I always get null when I do so. the ID is always empty even though I can view it inside the view. but even with empty id, I should be able to search my database.
that's where my second problem comes InvalidOperationException: Unable to resolve service for type 'MoviesDB.Models.ApplicationDbContext' while attempting to activate 'MoviesDB.Controllers.HomeController'.
So in Summary my View never sends my Controller the ID. and I also get this other error when I try to access my database. (this error happens on startup without me even trying to access that part of the functions)
My view is something like that. I'll only post the affected: so what happens here. my list loads exactly as expected and shows everything I need. after I click on Details and Access my controller it will not give me a value. I will explain later in the other block of code
<tbody>
#foreach (var item in Model.Search)
{
#item.Runtime
// each table row is assigned with the imdbID returned from the API. if the user clicks one of the rows
//then the system will 1st check the database if this movie exist in the database. if not then it will be added and then desplayed
//if the movie exist then it will be automatically desplayed to the user without making another API call.
<tr >
<td><img src="#item.Poster" class="img-thumbnail" alt="Responsive image" width="200"> </td>
<td>#item.Title</td>
<td>#item.Year #item.imdbID</td>
<td> <a asp-controller="Home" asp-action="FindMovie" asp-for="#item.imdbID">Details </a> </td>
</tr>
}
</tbody>
So what is happening here once I start up my project I will get that error :
InvalidOperationException: Unable to resolve service for type
'MoviesDB.Models.ApplicationDbContext' while attempting to activate
'MoviesDB.Controllers.HomeController'.
I don't know why this is happening, I will post my services on the next block just in case there is something I am missing in there. well now if I commented out all the database things and just have inside FindMovie action
Console.WriteLine("I am in Find" + imdbID);
I will only get "I am in Find" but I will not have an id next to it. so as it seems I am not sending the ID
private readonly ApplicationDbContext _db;
[BindProperty]
public Movies movies { get; set; }
public HomeController(ApplicationDbContext db)
{
_db = db;
}
public IActionResult Index()
{
return View();
}
[HttpGet]
public IActionResult FindMovie()
{
return View();
}
[HttpPost]
public IActionResult FindMovie(string imdbID)
{
Console.WriteLine("I am in Find" + imdbID);
var item = _db.Movies.Where(s => s.imdbID.Equals(imdbID)).FirstOrDefault();
if (item != null)
{
return NotFound();
}
return Content("Id is: {imdbID}");
}
and lastly here are my services:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddControllersWithViews();
services.AddRazorPages();
I have found what the problem was. When creating a new project with visual studio.
if you choose to create Authentication , it will create a dbcontext for you inside a folder called Data. it so happened this file to be called ApplicationDbContext as well. out of coincidence I named it the same.
what I did to resolve the error was to rename my own ApplicationDbContext to something new and add it in services and it worked perfectly. it was a structure error I guess.
My application is built in angular 7 and has a service that requests data from the WebApi that has EntityFramewrok to return the information.
The problem is that the numeric fields that have more than 18 digits are arriving incorrectly (for example the number 23434343434345353453,35 shows it as 23434343434345353000) when the service receives them.
I did tests and the EntityFramework loads the data well.
Finally, when I insert the data from my angular application, they are inserting well with the 18 or 20 digits I need, this because the model is created with the big.js library.
Front-end: Angular
Back-end: WebApi with ASP .NET MVC and EntityFramework
Component
import Big from 'big.js';
export class Parametro {
NRO_CONVENIO: string;
FEC_INICIO_NEGOCIACION: Date;
FEC_FIN_NEGOCIACION: Date;
VLR_CUPO_APROBADO: Big;
VLR_CUPO_UTILIZADO: Big;
VLR_CUPO_APROBADO_STORAGE: Big;
VLR_CUPO_UTILIZADO_STORAGE: Big;
ESTADO_DISPONIBLE: string;
ISEDIT: boolean;
}
export class ParametrosNegociacionService {
formData: Parametro;
list: Observable<Parametro>;
readonly rootURL = environment.baseUrl;
constructor(private http: HttpClient) { }
postParametro(formData: Parametro) {
return this.http.post(this.rootURL + '/ParametrosNegociacion', formData);
}
refreshList() {
this.http.get<Observable<Parametro>>(this.rootURL + '/ParametrosNegociacion')
.toPromise().then(res => {
this.list = res as Observable<Parametro>;
this.list.forEach(element => {
//Here the large number arrives badly
element.VLR_CUPO_APROBADO_STORAGE = element.VLR_CUPO_APROBADO;
});
});
}
...
}
View
<table id="dataTable" class="dataTable">
<thead class="headerStyle">
<tr>
<th>Vlr Cupo Aprobado</th>
</tr>
</thead>
<tbody>
<tr class="rowStyle" *ngFor="let emp of service.list">
<!--Here the large number showon badly -->
<td>{{emp.VLR_CUPO_APROBADO }}</td>
</tr>
</tbody>
</table>
When the data is received in the http.get, the numerical values misplace the information.
How can I receive the information of the large numbers correctly when I make the http.get request of all the information.
I grab any comments or ideas you have to solve this problem
Try to change the type of VLR_CUPO_APROBAD to string, because your dont need this value to an arithmetic operation, but only for display.
The problem with Javascript is the manipulation of big numbers.
I had the same problem with PHP, and that was a good solution for me
im using the folders that are supplied with the asp.net web application .net framework , and I'm trying to create a view fo the users that are signing in but it doesn't work even that I did manage to create a view for the roles, I did the same thing with the users but here it just doesn't work
here is the controller code
public ActionResult Index( )
{
var Users = context.Users.ToList();
return View(Users);
}
here is the view
#model List<A11_RBS.Models.ApplicationDbContext>
....
<table class="table">
<tr>
<th>#Html.DisplayNameFor(DbModel => Model)</th>
</tr>
#if (Model.Count() == 0)
{
<tr>
<td colspan="7">No records match search criteria</td>
</tr>
}
else
{
foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(DbModel =>item.Users)</td>
</tr>
}
}
</table>
the error is :
The model item passed into the dictionary is of type 'System.Collections.Generic.List'1[A11_RBS.Models.ApplicationUser]', but this dictionary requires a model item of type 'System.Collections.Generic.List'1[A11_RBS.Models.ApplicationDbContext]'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
My guess is the problem in the model but I don't know what to do about it
change ApplicationDbContext to ApplicationUser as suggested by the exception
you are sending an applicationUser model to the view but you are trying to use it as an ApplicationDbContext.
var Users = context.Users.ToList();
return View(Users);
So I am following the example at http://holsson.wordpress.com/2011/08/24/microsoft-dynamics-crm-2011-online-integration-getting-started-late-bound/ to try and create an MVC 5 site that uses CRM as the backing data. I created a CRMAccount Controller (Could't make one called Account as it was used by the Identity system).
I am able to successfully query the CRM System but when i try to use the Razor Code below in my view, I get the name, but nothing under the accountid is displayed. The item returned by accountid is a GUID, If I try to set it to a string, the DisplayFor complains that it can't render that.
#model IEnumerable<Microsoft.Xrm.Sdk.Entity>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<table>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item["accountid"])
</td>
<td>
#Html.DisplayFor(modelItem => item["name"])
</td>
</tr>
}
</table>
I am only doing this right now for Proof Of Concept. Eventually, I want to put the two together as a drop down box, but if I can't get the GUID to pull correctly, I'm going to have problems.
EDIT:-------------------------------------------------------------------
I was asked to post the controller code, though something similar was in the example i linked to above.
Here's the code used in my controller.
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
namespace ExternalEntities.Controllers
{
public class CRMAccountController : Controller
{
// GET: CRMAccount
public ActionResult Index()
{
var service = Session["ServiceProxy"] as IOrganizationService;
if (service != null)
{
var context = new OrganizationServiceContext(service);
IQueryable<Entity> query = from e in context.CreateQuery("account") select e;
List<Entity> accts = query.ToList();
return View(accts);
}
return RedirectToAction("Login", "Account");
}
}
}
try
#Html.DisplayFor(modelItem => item.accountid)
instead of
#Html.DisplayFor(modelItem => item["accountid"])
for intellisense, also can you show the controller please.
Edited after some comments back and forth:
Maybe you have a DisplayTemplate that is on your way? Try to do #item["accountid"] and see if it still blank. (not using DisplayFor)
I'm trying to recreate MVC Music Store but I've faced an error which I can't handle: "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection". The error is related to the following line in the ShoppingCart Index view:
#Html.ActionLink(item.Product.Title, "Details", "Store", new { id = item.ProductId }, null)
ShoppingCartController:
public class ShoppingCartController : Controller
{
OnlineStoreDbContext db = new OnlineStoreDbContext();
//
// GET: /ShoppingCart/
public ActionResult Index()
{
var cart = ShoppingCart.GetCart(this.HttpContext);
var viewModel = new ShoppingCartViewModel
{
CartItems = cart.GetCartItems(),
CartTotal = cart.GetTotal()
};
return View(viewModel);
}
//
// GET: /Store/AddToCart/5
public ActionResult AddToCart(int id)
{
// Retrieve the album from the database
var addedProduct = db.Products.Single(product => product.ProductId == id);
// Add it to the shopping cart
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.AddToCart(addedProduct);
// Go back to the main store page for more shopping
return RedirectToAction("Index");
}
[HttpPost]
public ActionResult RemoveFromCart(int id)
{
// Remove the item from the cart
var cart = ShoppingCart.GetCart(this.HttpContext);
// Get the name of the album to display confirmation
string productName = db.Carts.Single(item => item.RecordId == id).Product.Title;
// Remove from cart
int itemCount = cart.RemoveFromCart(id);
// Display the confirmation message
var results = new ShoppingCartRemoveViewModel
{
Message = Server.HtmlEncode(productName) + " has been removed from your shopping cart.",
CartTotal = cart.GetTotal(),
CartCount = cart.GetCount(),
ItemCount = itemCount,
DeleteId = id
};
return Json(results);
}
//
// GET: /ShoppingCart/CartSummary
[ChildActionOnly]
public ActionResult CartSummary()
{
var cart = ShoppingCart.GetCart(this.HttpContext);
ViewData["CartCount"] = cart.GetCount();
return PartialView("CartSummary");
}
}
ShoppingCart Index View:
#model OnlineStoreMVC.UI.ViewModels.ShoppingCartViewModel
#{
ViewBag.Title = "Shopping Cart";
}
<script src="/Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
// Document.ready -> link up remove event handler
$(".RemoveLink").click(function () {
// Get the id from the link
var recordToDelete = $(this).attr("data-id");
if (recordToDelete != '') {
// Perform the ajax post
$.post("/ShoppingCart/RemoveFromCart", { "id": recordToDelete },
function (data) {
// Successful requests get here
// Update the page elements
if (data.ItemCount == 0) {
$('#row-' + data.DeleteId).fadeOut('slow');
} else {
$('#item-count-' + data.DeleteId).text(data.ItemCount);
}
$('#cart-total').text(data.CartTotal);
$('#update-message').text(data.Message);
$('#cart-status').text('Cart (' + data.CartCount + ')');
});
}
});
});
function handleUpdate() {
// Load and deserialize the returned JSON data
var json = context.get_data();
var data = Sys.Serialization.JavaScriptSerializer.deserialize(json);
// Update the page elements
if (data.ItemCount == 0) {
$('#row-' + data.DeleteId).fadeOut('slow');
} else {
$('#item-count-' + data.DeleteId).text(data.ItemCount);
}
$('#cart-total').text(data.CartTotal);
$('#update-message').text(data.Message);
$('#cart-status').text('Cart (' + data.CartCount + ')');
}
</script>
<h3>
<em>Review</em> your cart:
</h3>
<p class="button">
#Html.ActionLink("Checkout", "AddressAndPayment", "Checkout")
</p>
<div id="update-message">
</div>
<table>
<tr>
<th>
Movie Title
</th>
<th>
Price (each)
</th>
<th>
Quantity
</th>
<th></th>
</tr>
#foreach (var item in Model.CartItems)
{
<tr id="row-#item.RecordId">
<td>
#Html.ActionLink(item.Product.Title, "Details", "Store", new { id = item.ProductId }, null)
</td>
<td>
#item.Product.Price
</td>
<td id="item-count-#item.RecordId">
#item.Count
</td>
<td>
Remove from cart
</td>
</tr>
}
<tr>
<td>
Total
</td>
<td></td>
<td></td>
<td id="cart-total">
#Model.CartTotal
</td>
</tr>
</table>
Edit:
public class ShoppingCart
{
string ShoppingCartId { get; set; }
public const string CartSessionKey = "CartId";
public static ShoppingCart GetCart(HttpContextBase context)
{
var cart = new ShoppingCart();
cart.ShoppingCartId = cart.GetCartId(context);
return cart;
}
public static ShoppingCart GetCart(Controller controller)
{
return GetCart(controller.HttpContext);
}
}
This error means pretty much exactly what it says. Somewhere, you've disposed of your application context instance, and then tried to make another query with it. This happens frequently when you're misusing lazy loading and perhaps being a little over-eager with disposing your context (wrapping it in a using block) for example.
I'm not seeing any likely culprit in the code you posted but ShoppingCart.GetCart looks like a prime candidate for further investigation.
Basically, you want to do two things. First, you want to get a handle on what's actually being utilized by your action/views. If you're accessing related items to a cart, or something, then you should consider eager-loading those with Include. Second, you need to ensure that you context sticks around throughout the period it needs to be used. If you're lazy loading items in your view, and you intend to do that, then you'll need to make it last the life of the request: just don't use using and rely on the Dispose method of the controller for disposing of it.
That's generalized advice though. Since I believe your issue lies in this GetCart method, if that's actually the case, then you need to approach it slightly differently. First, you can ensure that GetCart returns a fully-baked result, that will not allow further querying. In cases where you're returning an enumerable, you can normally clear this up just by using .AsList(). Since this is likely just returning a single object, you would need to map it to a DTO or something: anything other than the actual entity class.
Your other option is to inject your context to the method. Normally, injecting into the class would be preferred, but it looks like you're dealing with a static class here. Basically, you want to allow your controller to create and dispose the context and then just pass it as a parameter to your GetCart method, so that it uses the context in the controller instead of creating its own. Depending on your applications needs, you might actually consider implementing some dependency injection framework to handle tasks like these.