recursive function for hierarchically data - asp.net

my model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace amief.Models
{
public class WebsiteModels
{
public static void getPagesForPage(int pageId, dbDataContext db, List<page> myPages)
{
var pages = (from p in db.pages
where p.pageParent == pageId
select p);
foreach (var item in pages)
{
myPages.Add(item);
getPagesForPage(item.pageId, db, myPages);
}
}
}
}
calling the procudure
List<page> myPages = null;
WebsiteModels.getPagesForPage(0, db,myPages);
i'm getting an error
System.NullReferenceException was unhandled by user code
Message=Object reference not set to an instance of an object.
on line "myPages.Add(item);"
I don't understand the error...

You're setting myPages to null before passing it to WebsiteModels.getPagesForPage(). Therefore, the calls to myPages.Add(item); in your loop raise a NullReferenceException because you can't call a method on a null object.
You probably want:
List<page> myPages = new List<page>();
WebsiteModels.getPagesForPage(0, db, myPages);

Well, "myPages" IS null, so calling a method on it results i a NullReferenceException. You should rather write
myPages = new List<page>();

Related

Json break on bad column name [duplicate]

I'm trying to deserialize some JSON objects using Json.NET. I've found however that when I deserialize an object that doesn't have the properties I'm looking for that no error is thrown up but a default value is returned for the properties when I access them. It's important that I'm able to detect when I've deserialized the wrong type of object. Example code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Json_Fail_Test
{
class Program
{
[JsonObject(MemberSerialization.OptOut)]
private class MyJsonObjView
{
[JsonProperty("MyJsonInt")]
public int MyJsonInt { get; set; }
}
const string correctData = #"
{
'MyJsonInt': 42
}";
const string wrongData = #"
{
'SomeOtherProperty': 'fbe8c20b'
}";
static void Main(string[] args)
{
var goodObj = JsonConvert.DeserializeObject<MyJsonObjView>(correctData);
System.Console.Out.WriteLine(goodObj.MyJsonInt.ToString());
var badObj = JsonConvert.DeserializeObject<MyJsonObjView>(wrongData);
System.Console.Out.WriteLine(badObj.MyJsonInt.ToString());
}
}
}
The output of this program is:
42
0
I would prefer an exception be thrown to failing silently. Short of that is there a way to detect if the serialization failed to find a parameter?
I know I can parse the data with a Json object and then check for the parameter with a key value lookup but the codebase I'm in uses the pattern above and I'd like keep that consistent if it's possible.
The Json.Net serializer has a MissingMemberHandling setting which you can set to Error. (The default is Ignore.) This will cause the serializer to throw a JsonSerializationException during deserialization whenever it encounters a JSON property for which there is no corresponding property in the target class.
static void Main(string[] args)
{
try
{
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MissingMemberHandling = MissingMemberHandling.Error;
var goodObj = JsonConvert.DeserializeObject<MyJsonObjView>(correctData, settings);
System.Console.Out.WriteLine(goodObj.MyJsonInt.ToString());
var badObj = JsonConvert.DeserializeObject<MyJsonObjView>(wrongData, settings);
System.Console.Out.WriteLine(badObj.MyJsonInt.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.GetType().Name + ": " + ex.Message);
}
}
Result:
42
JsonSerializationException: Could not find member 'SomeOtherProperty' on object
of type 'MyJsonObjView'. Path 'SomeOtherProperty', line 3, position 33.
See: MissingMemberHandling setting.
Just add [JsonProperty(Required = Required.Always)] to the required properties and it'll throw exception if the property is not there while deserializing.
[JsonProperty(Required = Required.Always)]
public int MyJsonInt { get; set; }
Put the following attribute on required properties:
[DataMember(IsRequired = true)]
If the member is not present, it will throw a Newtonsoft.Json.JsonSerializationException.
As Brian suggested below, you will also need this attribute on your class:
[DataContract]
As #dbc tells in comments:
At deserialization:
If your Model has a property that your JSON does not, and you want that to be an error, use [JsonProperty(Required = Required.Always)].
At serialization:
If your JSON has a property that your Model does not, and you want that to be an error, use MissingMemberHandling = MissingMemberHandling.Error.
also using [DataMember(IsRequired = true)] for error at deserialization is true when proeprty type is nullable.
Just define your members in your definition class with a question mark '?' int?:
private class MyJsonObjView
{
[JsonProperty("MyJsonInt")]
public int? MyJsonInt { get; set; }
}
When it is not initialized, it will just be null, otherwise it will be a valid value. This allows you to have settings optional and evaluate them on a per-setting basis.

Pass data between controllers using method void

I need to pass values from one controllaro to a method from another controller.
or is there another way to pass data to an object so that object takes care of doing all the operations receiving values from other controllers
PRIMARY CONTROLLER
DateTime TimeLog = DateTime.Now;
LogController.Insert(TimeLog);
LOG CONTROLLER
using PROGRAM.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace PROGRAM.Controllers
{
public class LogController : Controller
{
Entities db = new Entities();
internal static void Insert(DateTime TimeLog)
{
LogModel log = new LogModel();
log.User = Session["User"].ToString();
log.TimeLog = TimeLog;
db.Log_Arqueo.Add(log);
db.SaveChanges();
}
}
}
ERROR
Severity Code Description Project File Line Status deleted
Error CS0120 An object reference is required for the non-static 'Controller.Session' field, method, or property PROGRAM\Controllers\LogController.cs 17 Active

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";
}

Populating a Telerik Grid using ViewModel (MVC3)

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

Resources