Populating a Telerik Grid using ViewModel (MVC3) - grid

Ok, this is a really newbie question but I am stumped.
I am trying to use a ViewModel to get my data from an entity object and populate the telerik mvc grid.
At this point I am a bit confused and need your help.
I understand the error message but I am not sure how I need to fix this since I am really new to MVC.
----ERROR----
Error 1 Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Linq.IQueryable'. An explicit conversion exists (are you missing a cast?) ProjectRepository.cs 23 20 MvcMyAPP
I have this viewmodel:
--VIEWMODEL--
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.UI.WebControls;
namespace mvcMyModel.ViewModels
{
public class ProjectViewModel
{
public IQueryable<mvcMyAPP.Models.ProjectRepository> ProjectList
{
get;
set;
}
}
}
--CONTROLLER--
namespace MvcMyAPP.Controllers
{
public class HomeController : Controller
{
// GET: /Home/
ProjectRepository Repository = new ProjectRepository();
public ActionResult Index()
{
ProjectViewModel objProjectViewModel = new ProjectViewModel();
objProjectViewModel.ProjectList = Repository.GetProjects();
return View(objProjectViewModel);
return View();
}
}
}
----REPOSITORY (MODEL)-----
namespace mvcMyAPP.Models
{
public class ProjectRepository
{
mvcMyAPP.Models.MYEntities MYDB = new MYEntities();
//Fetching data from table
public IQueryable<mvcMyAPP.ViewModels.ProjectViewModel> GetProjects()
{
var vProjects = (from tblProjects in MYDB.Projects
select tblProjects);
return vProjects;
}
}
---GRID---
#{Html.Telerik().Grid(Model.ProjectList)
.Name(
"Grid")
.Pageable()
.Sortable()
.Filterable()
.Groupable()
.Render();
}

You don't need the second return View() in the controller, but that isn't causing any problems.
You might try putting a cast on the return variable from your repository so it is returning the type specified in return:
// return vProjects;
// cast the return variable to return type
return (IQueryable<mvcMyAPP.ViewModels.ProjectViewModel>)vProjects;
I highly recommend Microsoft site for learning MVC, they have a great starting point for learning MVC.
http://www.asp.net/mvc

Related

Xamarin forms 4 shell navigation with complex parameters

I´m migratting a xamarin forms 3.x app with Prism to forms 4 with shell navigation.
Do I have to create my custom solution to pass complex parameters to the new page or Xamarin has some buildin feature to receive other than string parameters?
Thanks.
As far as I know, and, reading the docs, the only samples regard passing simple data, like string when navigating.
However, I was able to find an Issue (and Pull Request), for passing objects/ Models, for the next version (I assume this is the case you are referring to).
You can track it here.
I've run some tests which seems to be working. I'm relatively new to Xamarin, hence recommend caution and welcome any feedback for any potential issues I may be overlooking.
I wrote an extension to Shell to accept a data object parameter 'navigationData' as follows:-
await Shell.Current.GoToAsync(state, navigationData, animate);
The extension ...
namespace Xamarin.Forms
{
public static class ShellExtensions
{
public static async Task GoToAsync(this Shell shell, ShellNavigationState state, object navigationData, bool animate=false)
{
shell.Navigated += async (sender, e) =>
{
if ((Shell.Current?.CurrentItem?.CurrentItem as IShellSectionController)?.PresentedPage is MyContentPage
p) await p.InitializeAsync(navigationData).ConfigureAwait(false);
};
await shell.GoToAsync(state, animate);
}
}
}
As shown above the extension:-
hooks to the Shell 'Navigated' event,
retrieves the 'current view (page)' as 'MyContentPage' i.e. subclassed ContentPage,
calls an InitializeAsync method on the view passing in the
navigationData parameter
the view then calls an InitializeAsync
method on the binding context (view model) passing the
navigationData parameter onto the viewModel.
In the extension method above, 'MyContentPage' is a custom abstract subclass of ContentPage with an InitializeAsync(navigationData) method that simply calls a similar method on the viewModel (binding context of the view).
Similarily, ViewModels subclass a custom ViewModelBase class that has a virtual InitializeAsync(navigationData). This can be overridden in the viewModel with the desired implementation and handling of the navigation data.
Simplified sample of Views, ViewModels and related base classes shown below
using System.Threading.Tasks;
using MyXamarinApp.ViewModels;
using Xamarin.Forms;
namespace MyXamarinApp.Views
{
public ItemDetailPage : MyContent<ItemDetailViewModel>{}
public ItemPage : MyContentPage<ItemViewModel>{}
public abstract class MyContentPage<T> : MyContentPage where T : ViewModelBase
{
protected T Vm;
protected override ViewModelBase VmBase => Vm as ViewModelBase;
protected MyContentPage()
{
BindingContext = Vm = ViewModelLocator.Resolve<T>();
}
private Comand _showDetailCommand;
public Command ShowDetailCommand
{
get { return _showDetailCommand ??= new Command(async () =>
await Shell.Current.GoToAsync("itemDetail", new NavigationDataObject())); }
}
}
public abstract class MyContentPage : ContentPage
{
protected abstract ViewModelBase VmBase { get; }
public virtual async Task InitializeAsync(object navigationData)
{
await VmBase.InitializeAsync(navigationData);
}
}
}
public class NavigationDataObject
{
'Properties' etc.
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace MyXamarinApp.ViewModels
{
public ItemViewModel : ViewModelBase{}
public ItemDetailViewModel : ViewModelBase
{
private NavigationDataObject _navData;
public override async Task InitializeAsync(object navigationData)
{
if (navigationData is NavigationDataObject navData)
{
_navData = navData;
}
await base.InitializeAsync(navigationData);
}
}
public abstract class ViewModelBase
{
public virtual Task InitializeAsync(object navigationData)
{
return Task.FromResult(false);
}
}
}
You can always serialize the model to a JSON string and un-serializes it on the other side?
async void Handle_ItemTapped(object sender, ItemTappedEventArgs e)
{
if (e.Item == null)
return;
DailyPnL PnLClicked = (DailyPnL)e.Item;
string jason = await Task.Run(() => JsonConvert.SerializeObject(PnLClicked));
await Shell.Current.GoToAsync($"viewdailypnl?pnlmodel={jason}");
//Deselect Item
((ListView)sender).SelectedItem = null;
}
Then in your code behind:
public string pnlmodel
{
set
{
string derulo = Uri.UnescapeDataString(value);
viewModel.PnL = Task.Run(() => JsonConvert.DeserializeObject<DailyPnL>(derulo)).Result;
}
}
There is a framework called Xamarin.Zero https://github.com/markjackmilian/Xam.Zero
It lets you use shell while giving you convenient ViewModel to ViewModel navigation, IOC.
You can user stored preferences to store complex data like:
private async void OnItemSelected(Item item)
{
if (item == null)
return;
var jsonstr = JsonConvert.SerializeObject(item);
//Clear the shared preferences in case there is any
Preferences.Clear();
//Store your complex json on a shared preference
Preferences.Set("Data", jsonstr);
await Shell.Current.GoToAsync(nameof(DetailsPage));
}
Retrieve it on the details page like:
bool hasKey = Preferences.ContainsKey("Data");
var content = Preferences.Get("Data", string.Empty);
Details details = hasKey ? JsonConvert.DeserializeObject<Model>(content) : null;

.NET Core 2.0 Localization across projects

I have 2 projects:
1. WebApi
2. Common
The resource files are in the WebApi, and the WebApi is calling the Common. However, the Common needs to get the string from the resource file. How can I do that?
I was able to resolve it using IStringLocalizerFactory to create the IStringLocalizer. Here is an example of the code that solved my problem:
var assemblyName = Assembly.GetEntryAssembly().GetName().Name;
return _localizerFactory.Create("ExceptionResource", assemblyName);
You make a resource file(s) in your business logic, you're a definitely not going to create a dependency between your business logic-project and your web-project in order to be able to access your Localization resources.
The key issue, as you wrote was:
"(...) resolve it using IStringLocalizerFactory to create the
IStringLocalizer".
A real life example a this could be
You can do it like you have written and which is similar to what is in the documentation
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization?view=aspnetcore-3.1#implement-a-strategy-to-select-the-languageculture-for-each-request
Here's an example of Damien Bod from his short manual
https://damienbod.com/2017/11/01/shared-localization-in-asp-net-core-mvc/
u
sing Microsoft.Extensions.Localization;
using System.Reflection;
namespace AspNetCoreMvcSharedLocalization.Resources
{
public class LocService
{
private readonly IStringLocalizer _localizer;
public LocService(IStringLocalizerFactory factory)
{
var type = typeof(SharedResource);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = factory.Create("SharedResource", assemblyName.Name);
}
public LocalizedString GetLocalizedHtmlString(string key)
{
return _localizer[key];
}
}
}
You don't actually need a dummy class, you could also do it like:
using Microsoft.Extensions.Localization;
namespace ….Business.LocalizationService
{
public interface ILocalizationMiddleware
{
public LocalizedString GetLocalizedString(string keyForResourceTable);
}
}
using Microsoft.Extensions.Localization;
using System.Reflection;
namespace ….Business.LocalizationService
{
public class LocalizationMiddleware : ILocalizationMiddleware
{
private readonly IStringLocalizer localizer;
public LocalizationMiddleware(IStringLocalizerFactory factory)
{
localizer = factory.Create("SharedResource", Assembly.GetExecutingAssembly().FullName);
}
public LocalizedString GetLocalizedString(string keyForResourceTable) { return localizer[keyForResourceTable]; }
}
}

Acumatica - Add Reports dropdown to Kit Assembly Screen

I have been trying to add a Reports dropdown to the Kit Assembly screen (IN307000). We have custom reports that are based on the KitInventoryID that will be generated to print a tag essentially and these reports need to be added to the actions of the screen. I noticed that there is normally a transfer in most Report screens that will be used to transfer data so I did write my own statement at the top. Here is what I have so far:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using PX.Data;
using PX.Objects.CS;
using PX.Objects.IN.Overrides.INDocumentRelease;
using PX.Objects.GL;
using PX.Objects.CM;
using System.Diagnostics;
using PX.Objects;
using PX.Objects.IN;
namespace PX.Objects.IN
{
public class KitAssemblyEntry_Extension:PXGraphExtension<KitAssemblyEntry>
{
public PXSelect<INKitRegister, Where<INKitRegister.docType, Equal<Current<INKitRegister.docType>>, And<INKitRegister.kitInventoryID, Equal<Current<INKitRegister.kitInventoryID>>>>> transfer;
public override void Initialize()
{
Report.AddMenuAction(MasterTag);
Report.MenuAutoOpen = true;
}
#region Event Handlers
public PXAction<INKitRegister> Report;
[PXButton]
[PXUIField(DisplayName = "Print Tag", MapEnableRights = PXCacheRights.Select)]
protected void report()
{ }
public PXAction<INKitRegister> MasterTag;
[PXUIField(DisplayName = "Sample/Value Tag", MapEnableRights = PXCacheRights.Select)]
[PXLookupButton]
public virtual IEnumerable masterTag(PXAdapter adapter)
{
INKitRegister doc = Base.transfer.Current;
if (doc != null)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters["DocType"] = this.transfer.Current.DocType;
parameters["ItemNumber"] = this.transfer.Current.KitInventoryID.ToString();
throw new PXReportRequiredException(parameters, "IN610004", "Sample/Value Tag");
}
}
#endregion
}
}
However, when I try to publish I get this error:
Building directory '\WebSiteValidationDomain\App_RuntimeCode\'.
\App_RuntimeCode\KitAssemblyEntry.cs(39): error CS1061: 'PX.Objects.IN.KitAssemblyEntry' does not contain a definition for 'transfer' and no extension method 'transfer' accepting a first argument of type 'PX.Objects.IN.KitAssemblyEntry' could be found (are you missing a using directive or an assembly reference?)
\App_RuntimeCode\KitAssemblyEntry.cs(39): error CS1061: 'PX.Objects.IN.KitAssemblyEntry' does not contain a definition for 'transfer' and no extension method 'transfer' accepting a first argument of type 'PX.Objects.IN.KitAssemblyEntry' could be found (are you missing a using directive or an assembly reference?)
I have also tried changing the INKitRegister doc = Base.transfer.Current;to INKitRegister doc = Base.Document.Current; but get this error:
\App_RuntimeCode\KitAssemblyEntry.cs(37): error CS0161: 'PX.Objects.IN.KitAssemblyEntry_Extension.masterTag(PX.Data.PXAdapter)': not all code paths return a value
\App_RuntimeCode\KitAssemblyEntry.cs(37): error CS0161: 'PX.Objects.IN.KitAssemblyEntry_Extension.masterTag(PX.Data.PXAdapter)': not all code paths return a value
Here is the fixed coded and it is working properly.
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using PX.Data;
using PX.Objects.CS;
using PX.Objects.IN.Overrides.INDocumentRelease;
using PX.Objects.GL;
using PX.Objects.CM;
using System.Diagnostics;
using PX.Objects;
using PX.Objects.IN;
namespace PX.Objects.IN
{
public class KitAssemblyEntry_Extension:PXGraphExtension<KitAssemblyEntry>
{
public PXSelect<INKitRegister, Where<INKitRegister.docType, Equal<Current<INKitRegister.docType>>, And<INKitRegister.kitInventoryID, Equal<Current<INKitRegister.kitInventoryID>>>>> transfer;
public override void Initialize()
{
Report.AddMenuAction(MasterTag);
Report.MenuAutoOpen = true;
}
#region Event Handlers
public PXAction<INKitRegister> Report;
[PXButton]
[PXUIField(DisplayName = "Print Tag", MapEnableRights = PXCacheRights.Select)]
protected void report()
{ }
public PXAction<INKitRegister> MasterTag;
[PXUIField(DisplayName = "Sample/Value Tag", MapEnableRights = PXCacheRights.Select)]
[PXLookupButton]
public virtual IEnumerable masterTag(PXAdapter adapter)
{
INKitRegister doc = Base.Document.Current;
if (doc != null)
{
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters["DocType"] = this.transfer.Current.DocType;
parameters["ItemNumber"] = this.transfer.Current.KitInventoryID.ToString();
throw new PXReportRequiredException(parameters, "IN610004", "Sample/Value Tag");
}
return adapter.Get();
}
#endregion
}
}

What is the correct model binding architecture for this situation?

I'm replacing some old webservice code with WebApi, and I've got a situation where the code used to do something like this:
If Request.QueryString("value") = 1 Then
{do first action}
Else
{do second action}
End If
Each action is totally different, and each has an independent set of other query string parameters.
In my new version, I'm modelling this as:
Public Function FirstAction(model as FirstActionModel) As HttpResponseMessage
and
Public Function SecondAction(model as SecondActionModel) As HttpResponseMessage
The catch is that the incoming request is going to just call /api/actions?actiontype=1&params... or /api/actions?actiontype=2&params... and the params are different.
I want to be able to route a request with actiontype=1 to FirstAction, and actiontype=2 to SecondAction. But I can't use routing, because the important value is in the query string, not the path.
How can I do this?
As i've mentioned in comments you can use IHttpActionSelector to achieve this. But instead of implementing interface directly you can inherit from default implementation.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Http.Controllers;
namespace WebApplication1
{
public class CustomHttpActionSelector : ApiControllerActionSelector
{
public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
{
var urlParam = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query);
var actionType = urlParam["actiontype"];
if (actionType == null)
return base.SelectAction(controllerContext);
MethodInfo methodInfo;
if (actionType.ToString() == "1")
methodInfo = controllerContext.ControllerDescriptor.ControllerType.GetMethod("Action1");
else
methodInfo = controllerContext.ControllerDescriptor.ControllerType.GetMethod("Action2");
return new ReflectedHttpActionDescriptor(controllerContext.ControllerDescriptor, methodInfo);
}
}
}
And to register it you need to add following line to your WebApiConfig.cs file:
config.Services.Replace(typeof(IHttpActionSelector), new CustomHttpActionSelector());
In your controller you than add two methods Action1 and Action2:
public string Action1(string param)
{
return "123";
}
public string Action2(string param)
{
return "345";
}

How can i using GetObjectByKey in mvc 5 using entity framword 6

I am using mvc 5 and ef 6 to build a project. I was simplify the retrieval code by adding some methods to partial class entity context. This is how i do it:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;
using System.Linq.Expressions;
using System.Data.Entity.Core;
namespace MyShop.Models
{
public partial class DataEntities
{
public T GetById<T>(object id) where T : class
{
EntityKey key = CreateKey<T>(id);
return (T)GetObjectByKey(key);
}
private EntityKey CreateKey<T>(object id)
{
var type = typeof(T);
return new EntityKey("MyEntities." + "." + type.Name, "Id", id);
}
}
But it error at GetObjectByKey though i was add entityframwork 6.dll in my project, and i tried add some references but it don't work.
Can you help me fix the error.
Thanks you for read.
Phuong

Resources